Skip to content

v01: core: add MemorySwapLimit= to limit memory+swap#2171

Closed
walyong wants to merge 1 commit intosystemd:masterfrom
walyong:memcg_v01
Closed

v01: core: add MemorySwapLimit= to limit memory+swap#2171
walyong wants to merge 1 commit intosystemd:masterfrom
walyong:memcg_v01

Conversation

@walyong
Copy link
Contributor

@walyong walyong commented Dec 15, 2015

Similar to MemoryLimit=, MemorySwapLimit= limits memory+swap usage. This
controls the "memory.memsw.limit_in_bytes" control group attribute.
And when MemorySwapLimit= was set, if MemoryLimit= was not set or bigger
than MemorySwapLimit= then set MemoryLimit= as same amount of
value with MemorySwapLimit=.

https://www.kernel.org/doc/Documentation/cgroups/memory.txt:

memory.limit_in_bytes # set/show limit of memory usage
memory.memsw.limit_in_bytes # set/show limit of memory+Swap usage

Similar to MemoryLimit=, MemorySwapLimit= limits memory+swap usage. This
controls the "memory.memsw.limit_in_bytes" control group attribute.
And when MemorySwapLimit= was set, if MemoryLimit= was not set or bigger
than MemorySwapLimit= then set MemoryLimit= as same amount of
value with MemorySwapLimit=.
@evverx
Copy link
Contributor

evverx commented Dec 15, 2015

Are there any tests?

@walyong
Copy link
Contributor Author

walyong commented Dec 16, 2015

I wrote local test code memory-swap-limit-test.c:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>


static int get_memory_cgroup_of_my(char **path) {
    char *p = NULL, *proc_cgroup = NULL;
    pid_t pid = getpid();
    char buf[LINE_MAX];
    FILE *f = NULL;

    asprintf(&proc_cgroup, "/proc/%d/cgroup", pid);

    f = fopen(proc_cgroup, "re");
    if (!f)
        return -errno;

    for (;;) {
        char *name = NULL;
        int i;

        if (!fgets(buf, sizeof(buf), f)) {
            if (ferror(f))
                return -errno;

            break;
        }

        sscanf(buf, "%d:%m[^:]:%ms", &i, &name, &p);

        if (!strcmp(name, "memory")) {
            *path = p;

            free(proc_cgroup);
            fclose(f);
            return 0;
        }
    }

    free(proc_cgroup);
    fclose(f);

    return -ENODATA;
}

static int find_cgroup_path(char **path) {
    char *cg_node = NULL;
    char *p = NULL;
    int r;

    r = get_memory_cgroup_of_my(&cg_node);
    if (r < 0)
        return r;

    if (!strcmp(cg_node, "/")) {
        fprintf(stderr, "Should be run as systemd service\n");
        free(cg_node);
        return -ENOTSUP;
    }

    asprintf(&p, "/sys/fs/cgroup/memory%s", cg_node);

    *path = p;

    free(cg_node);
    return 0;
}

static void display_memcg_info(const char *path) {
    char *list[] = {
        "memory.usage_in_bytes",
        "memory.limit_in_bytes",
        "memory.failcnt",
        "memory.memsw.usage_in_bytes",
        "memory.memsw.limit_in_bytes",
        "memory.memsw.failcnt",
        NULL
    };

    char node[PATH_MAX];
    char buf[LINE_MAX];
    int i;

    for (i = 0; list[i] != NULL; i++) {
        FILE *f = NULL;

        snprintf(node, PATH_MAX, "%s/%s", path, list[i]);

        f = fopen(node, "re");
        for (;;) {
            if (!fgets(buf, sizeof(buf), f))
                break;

            printf("%s: %s\n",list[i], buf);
        }
        fclose(f);
    }
}

int main(int argc, char *argv[]) {
    char *cg_path = NULL;
    void *p = NULL;
    int i, r;

    r = find_cgroup_path(&cg_path);
    if (r < 0)
        return EXIT_FAILURE;

    printf("cgroup path: %s\n", cg_path);
    display_memcg_info(cg_path);

    for (i = 0;; i++) {
        p = malloc(500 << 10);
        if (!p) {
            fprintf(stderr, "!!! malloc failed: %s\n", strerror(errno));
            continue;
        }

        memset(p, 0x0, 500 << 10);
        fprintf(stdout, "!!! malloc successed. Count %d\n", i+1);

        display_memcg_info(cg_path);
        sleep(1);
    }

    return 0;
}

And also I wrote a service file to test as memory-swap-limit-test.service:

[Unit]
Description=Test MemorySwapLimit=

[Service]
ExecStart=/home/walyong/tmp/memory-swap-limit/memory-swap-limit-test
MemoryLimit=5M
MemorySwapLimit=10M
StandardOutput=journal
StandardError=inherit

And run:

[root@laptop system]# systemctl daemon-reload
[root@laptop system]# systemctl start memory-swap-limit.service; systemctl status memory-swap-limit.service
● memory-swap-limit.service - Test MemorySwapLimit=
   Loaded: loaded (/usr/lib/systemd/system/memory-swap-limit.service; static; vendor preset: disabled)
   Active: active (running) since Wed 2015-12-16 13:37:44 KST; 96ms ago
 Main PID: 14870 (memory-swap-lim)
   Memory: 596.0K (limit: 5.0M) (with swap limit: 10.0M)
   CGroup: /system.slice/memory-swap-limit.service
           └─14870 /home/walyong/tmp/memory-swap-limit/memory-swap-limit-test

Dec 16 13:37:44 laptop.walyong.com systemd[1]: Started Test MemorySwapLimit=.

Finally, I can get below logs:

Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: cgroup path: /sys/fs/cgroup/memory/system.slice/memory-swap-limit.service
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.usage_in_bytes: 126976
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.limit_in_bytes: 5242880
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.failcnt: 0
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.usage_in_bytes: 114688
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.limit_in_bytes: 10485760
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.failcnt: 0
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: !!! malloc successed. Count 1
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.usage_in_bytes: 626688
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.limit_in_bytes: 5242880
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.failcnt: 0
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.usage_in_bytes: 614400
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.limit_in_bytes: 10485760
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.failcnt: 0
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: !!! malloc successed. Count 2
...
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: !!! malloc successed. Count 17
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.usage_in_bytes: 5115904
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.limit_in_bytes: 5242880
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.failcnt: 406
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.usage_in_bytes: 8982528
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.limit_in_bytes: 10485760
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.failcnt: 0
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: !!! malloc successed. Count 18
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.usage_in_bytes: 5115904
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.limit_in_bytes: 5242880
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.failcnt: 446
Dec 16 13:38:01 laptop.walyong.com memory-swap-limit-test[14870]: memory.memsw.usage_in_bytes: 9506816
Dec 16 13:38:04 laptop.walyong.com kernel: memory-swap-lim invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=0
Dec 16 13:38:04 laptop.walyong.com kernel: memory-swap-lim cpuset=/ mems_allowed=0
Dec 16 13:38:04 laptop.walyong.com kernel: CPU: 0 PID: 14870 Comm: memory-swap-lim Not tainted 4.2.6-301.fc23.x86_64+debug #1
Dec 16 13:38:04 laptop.walyong.com kernel: Hardware name: SAMSUNG ELECTRONICS CO., LTD. 770Z5E/780Z5E/NT770Z5E-MOBIL, BIOS P06ABU.145.140219.SH 02/19/2014
Dec 16 13:38:04 laptop.walyong.com kernel:  0000000000000000 0000000040ace418 ffff8801a820bc98 ffffffff81869b26
Dec 16 13:38:04 laptop.walyong.com kernel:  ffffffff81868ce7 ffff8800b9f0aa40 ffff8801a820bd28 ffffffff81868cec
Dec 16 13:38:04 laptop.walyong.com kernel:  0000000000000000 0000000000000206 ffffffff81e74220 ffffffff81a212e0
Dec 16 13:38:04 laptop.walyong.com kernel: Call Trace:
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81869b26>] dump_stack+0x4c/0x65
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81868ce7>] ? dump_header+0x86/0x261
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81868cec>] dump_header+0x8b/0x261
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff8110814d>] ? trace_hardirqs_on+0xd/0x10
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff811e6a8a>] oom_kill_process+0x1ea/0x3d0
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81261e83>] mem_cgroup_oom_synchronize+0x6c3/0x700
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff8125a8b0>] ? mem_cgroup_css_online+0x250/0x250
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff811e73e3>] pagefault_out_of_memory+0x13/0x80
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81071752>] mm_fault_error+0x82/0x160
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81071c6f>] __do_page_fault+0x43f/0x470
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81071ccf>] do_page_fault+0x2f/0x80
Dec 16 13:38:04 laptop.walyong.com kernel:  [<ffffffff81875808>] page_fault+0x28/0x30
Dec 16 13:38:04 laptop.walyong.com kernel: Task in /system.slice/memory-swap-limit.service killed as a result of limit of /system.slice/memory-swap-limit.service
Dec 16 13:38:04 laptop.walyong.com kernel: memory: usage 5048kB, limit 5120kB, failcnt 526
Dec 16 13:38:04 laptop.walyong.com kernel: memory+swap: usage 10240kB, limit 10240kB, failcnt 27
Dec 16 13:38:04 laptop.walyong.com kernel: kmem: usage 0kB, limit 9007199254740988kB, failcnt 0
Dec 16 13:38:04 laptop.walyong.com kernel: Memory cgroup stats for /system.slice/memory-swap-limit.service: cache:0KB rss:5048KB rss_huge:0KB mapped_file:0KB dirty:0KB write
Dec 16 13:38:04 laptop.walyong.com kernel: [ pid ]   uid  tgid total_vm      rss nr_ptes nr_pmds swapents oom_score_adj name
Dec 16 13:38:04 laptop.walyong.com kernel: [14870]     0 14870     3723     1421      11       3     1458             0 memory-swap-lim
Dec 16 13:38:04 laptop.walyong.com kernel: Memory cgroup out of memory: Kill process 14870 (memory-swap-lim) score 1096 or sacrifice child
Dec 16 13:38:04 laptop.walyong.com kernel: Killed process 14870 (memory-swap-lim) total-vm:14892kB, anon-rss:4340kB, file-rss:1344kB
Dec 16 13:38:04 laptop.walyong.com memory-swap-limit-test[14870]: memory.mem
Dec 16 13:38:04 laptop.walyong.com systemd[1]: memory-swap-limit.service: Main process exited, code=killed, status=9/KILL
Dec 16 13:38:04 laptop.walyong.com systemd[1]: memory-swap-limit.service: Unit entered failed state.
Dec 16 13:38:04 laptop.walyong.com systemd[1]: memory-swap-limit.service: Failed with result 'signal'.

And I'd also tested with only MemoryLimit= option:

[Unit]
Description=Test MemorySwapLimit=

[Service]
ExecStart=/home/walyong/tmp/memory-swap-limit/memory-swap-limit-test
MemoryLimit=5M
StandardOutput=journal
StandardError=inherit

Then, the service was not killed well:

Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: cgroup path: /sys/fs/cgroup/memory/system.slice/memory-swap-limit.service
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.usage_in_bytes: 249856
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.limit_in_bytes: 5242880
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.failcnt: 0
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.usage_in_bytes: 237568
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.limit_in_bytes: 9223372036854771712
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.failcnt: 0
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: !!! malloc successed. Count 1
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.usage_in_bytes: 749568
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.limit_in_bytes: 5242880
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.failcnt: 0
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.usage_in_bytes: 737280
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.limit_in_bytes: 9223372036854771712
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.failcnt: 0
Dec 16 13:35:46 laptop.walyong.com memory-swap-limit-test[14135]: !!! malloc successed. Count 2
...
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.failcnt: 0
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: !!! malloc successed. Count 68
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.usage_in_bytes: 5193728
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.limit_in_bytes: 5242880
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.failcnt: 3294
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.usage_in_bytes: 35192832
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.limit_in_bytes: 9223372036854771712
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.failcnt: 0
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: !!! malloc successed. Count 69
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.usage_in_bytes: 5132288
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.limit_in_bytes: 5242880
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.failcnt: 3374
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.usage_in_bytes: 35868672
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.limit_in_bytes: 9223372036854771712
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.failcnt: 0
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: !!! malloc successed. Count 70
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.usage_in_bytes: 5111808
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.limit_in_bytes: 5242880
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.failcnt: 3393
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.usage_in_bytes: 36302848
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.limit_in_bytes: 9223372036854771712
Dec 16 13:36:41 laptop.walyong.com memory-swap-limit-test[14135]: memory.memsw.failcnt: 0

So I had to stop that.

@poettering
Copy link
Member

At this point, I don't think we should support cgroups properties that have no future in the unified hierarchy. Or does this one have a counterpart on the unified hierarchy?

@poettering poettering added cgroups pid1 needs-reporter-feedback ❓ There's an unanswered question, the reporter needs to answer labels Dec 21, 2015
@walyong
Copy link
Contributor Author

walyong commented Dec 28, 2015

It seems currently being implemented now:
https://lkml.org/lkml/2015/12/10/259

I will create new PR after kernel has facility for accounting swap.
But, unified hierarchy cgroup is really new feature. Many of distros are still using legacy cgroup. So, I think, we have to support legacy cgroup for a while.

@poettering
Copy link
Member

Well, basically, I think we shouldn't add new support for something that has no future. I am fine howeve, to add support for something that has a clear future and then adding compat for old setups, if that's possible. Or in other words, as soon as it is clear how the settings will look like in the unified hierarchy, we can add support for this setting, and then also make it work on the legacy hierararchy too. But I am not keen on adding support for the legacy hierarchy before the unified hierarchy support is clear, because the exposed knobs should follow the new design, not the old design. I hope this makes sense?

Let's delay this until the swap memory knobs land in the kernel hence! Sorry!

@poettering poettering added postponed and removed needs-reporter-feedback ❓ There's an unanswered question, the reporter needs to answer labels Jan 12, 2016
@walyong walyong closed this Jan 27, 2016
@walyong walyong deleted the memcg_v01 branch January 27, 2016 02:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants