Received: by 2002:ad5:4acb:0:0:0:0:0 with SMTP id n11csp3486413imw; Mon, 11 Jul 2022 09:30:29 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vGBVgkJd7wW1UfVD8ESACzB64ceOlUrtpKNxnIXq6e1p6ryenEVY+BJImpdOLSi9LSLq2l X-Received: by 2002:a05:6a00:1803:b0:525:6ed7:cdc4 with SMTP id y3-20020a056a00180300b005256ed7cdc4mr18888605pfa.15.1657557029068; Mon, 11 Jul 2022 09:30:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1657557029; cv=none; d=google.com; s=arc-20160816; b=TdD7lMZsj0ACz7vH5YN7iDUFV413zPRQVFoNyQKLp3/Cr4/1ijgpObeRsY+MVIM5GX rPldtwGSE6e1TQDoB4pl6DezXmOmj4aHvsBnefFkUeaumiZExkyI97mxUgGn3cwfvGtZ OvzuXOqLOKatlJmMwr7S6NUOpGCP8kXm1CB7AxA8zcl6lhrEqRL1pel7myq+feZhHjfQ brHTCXp/GoXwlw/1zWERdAgOH1pH5QQmx90p+tOLCr4Nsi1mEnU2wV34qGUG7mk2Qp+j pq0ZijiEGmjIN1zdyY+G3RfomTkWz/puQLVnYukmxoY6NBGHY3De6jg+vMP/4f2dWvmM L5Cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=SNVfcaeOkyiq6FVIEaxSDCsydyKGK4n0IU9nmyOSxH8=; b=MBTxMUc5XWs4DV0FrGUZocjmWOH968dC3xbmc39ryKmtIIP9HJaAjh7KCV1Ex+fEJy krDbg2J6ykBYpYt1E70lirc1kZy0T+uCUTb4oCaggufvxljlSkTUvOmoZJcX3CcAkWgl TPEP8wXZ8s0Fhap0reBLjkMCcX7TcUlvzSALH39+1pay6A+CJJcarpOAM6pPmsajJmHP 0XwweQVnVUDBBhqL2FD+i5NGuPLVfCIhU5fvs8O+lqhDpTaUsayhOO6TvyHhYbkovFSW uFsI0IDEF8lhX8nu0VvUbfrRaQMvWI8TUnF0V+pUPE2NHQ+6FCQOiuEQSuL74TiQwrFQ xFbQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=lYbnIVXx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o19-20020a170903301300b0016c1a1bb2fasi8933570pla.569.2022.07.11.09.30.12; Mon, 11 Jul 2022 09:30:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=lYbnIVXx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231682AbiGKQ2u (ORCPT + 99 others); Mon, 11 Jul 2022 12:28:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50390 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231736AbiGKQ2k (ORCPT ); Mon, 11 Jul 2022 12:28:40 -0400 Received: from out0.migadu.com (out0.migadu.com [94.23.1.103]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B86F10E2; Mon, 11 Jul 2022 09:28:37 -0700 (PDT) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1657556915; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=SNVfcaeOkyiq6FVIEaxSDCsydyKGK4n0IU9nmyOSxH8=; b=lYbnIVXxY+nEpTl7H54GoIE1CC/WFSAkSY1mL3sOFBu5ixion91lo7tuVNfw4iPYMT89Jt OR4LSi4V7oQuwzOCPkq1wnf+DfsPCKnjUgLfdkpM0X6p5nL9FZGzhciW/3qUBtZnHFmF5R FaTw2mgY6U6IOUG/YVmiOSznH1+7J44= From: Roman Gushchin To: bpf@vger.kernel.org Cc: Shakeel Butt , Alexei Starovoitov , linux-kernel@vger.kernel.org, Roman Gushchin Subject: [PATCH bpf-next v2] bpf: reparent bpf maps on memcg offlining Date: Mon, 11 Jul 2022 09:28:27 -0700 Message-Id: <20220711162827.184743-1-roman.gushchin@linux.dev> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Migadu-Auth-User: linux.dev X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The memory consumed by a mpf map is always accounted to the memory cgroup of the process which created the map. The map can outlive the memory cgroup if it's used by processes in other cgroups or is pinned on bpffs. In this case the map pins the original cgroup in the dying state. For other types of objects (slab objects, non-slab kernel allocations, percpu objects and recently LRU pages) there is a reparenting process implemented: on cgroup offlining charged objects are getting reassigned to the parent cgroup. Because all charges and statistics are fully recursive it's a fairly cheap operation. For efficiency and consistency with other types of objects, let's do the same for bpf maps. Fortunately thanks to the objcg API, the required changes are minimal. Please, note that individual allocations (slabs, percpu and large kmallocs) already have the reparenting mechanism. This commit adds it to the saved map->memcg pointer by replacing it to map->objcg. Because dying cgroups are not visible for a user and all charges are recursive, this commit doesn't bring any behavior changes for a user. v2: added a missing const qualifier Signed-off-by: Roman Gushchin Reviewed-by: Shakeel Butt --- include/linux/bpf.h | 2 +- kernel/bpf/syscall.c | 35 +++++++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 2b21f2a3452f..85a4db3e0536 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -221,7 +221,7 @@ struct bpf_map { u32 btf_vmlinux_value_type_id; struct btf *btf; #ifdef CONFIG_MEMCG_KMEM - struct mem_cgroup *memcg; + struct obj_cgroup *objcg; #endif char name[BPF_OBJ_NAME_LEN]; struct bpf_map_off_arr *off_arr; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index ab688d85b2c6..ef60dbc21b17 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -419,35 +419,52 @@ void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock) #ifdef CONFIG_MEMCG_KMEM static void bpf_map_save_memcg(struct bpf_map *map) { - map->memcg = get_mem_cgroup_from_mm(current->mm); + /* Currently if a map is created by a process belonging to the root + * memory cgroup, get_obj_cgroup_from_current() will return NULL. + * So we have to check map->objcg for being NULL each time it's + * being used. + */ + map->objcg = get_obj_cgroup_from_current(); } static void bpf_map_release_memcg(struct bpf_map *map) { - mem_cgroup_put(map->memcg); + if (map->objcg) + obj_cgroup_put(map->objcg); +} + +static struct mem_cgroup *bpf_map_get_memcg(const struct bpf_map *map) { + if (map->objcg) + return get_mem_cgroup_from_objcg(map->objcg); + + return root_mem_cgroup; } void *bpf_map_kmalloc_node(const struct bpf_map *map, size_t size, gfp_t flags, int node) { - struct mem_cgroup *old_memcg; + struct mem_cgroup *memcg, *old_memcg; void *ptr; - old_memcg = set_active_memcg(map->memcg); + memcg = bpf_map_get_memcg(map); + old_memcg = set_active_memcg(memcg); ptr = kmalloc_node(size, flags | __GFP_ACCOUNT, node); set_active_memcg(old_memcg); + mem_cgroup_put(memcg); return ptr; } void *bpf_map_kzalloc(const struct bpf_map *map, size_t size, gfp_t flags) { - struct mem_cgroup *old_memcg; + struct mem_cgroup *memcg, *old_memcg; void *ptr; - old_memcg = set_active_memcg(map->memcg); + memcg = bpf_map_get_memcg(map); + old_memcg = set_active_memcg(memcg); ptr = kzalloc(size, flags | __GFP_ACCOUNT); set_active_memcg(old_memcg); + mem_cgroup_put(memcg); return ptr; } @@ -455,12 +472,14 @@ void *bpf_map_kzalloc(const struct bpf_map *map, size_t size, gfp_t flags) void __percpu *bpf_map_alloc_percpu(const struct bpf_map *map, size_t size, size_t align, gfp_t flags) { - struct mem_cgroup *old_memcg; + struct mem_cgroup *memcg, *old_memcg; void __percpu *ptr; - old_memcg = set_active_memcg(map->memcg); + memcg = bpf_map_get_memcg(map); + old_memcg = set_active_memcg(memcg); ptr = __alloc_percpu_gfp(size, align, flags | __GFP_ACCOUNT); set_active_memcg(old_memcg); + mem_cgroup_put(memcg); return ptr; } -- 2.36.1