From patchwork Tue Sep 1 00:06:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Minchan Kim X-Patchwork-Id: 11747129 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7D016109B for ; Tue, 1 Sep 2020 00:07:53 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 3DE4F2100A for ; Tue, 1 Sep 2020 00:07:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="loncq7c6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3DE4F2100A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 544216B0037; Mon, 31 Aug 2020 20:07:52 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 4F5F46B0055; Mon, 31 Aug 2020 20:07:52 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 3BD5D6B005A; Mon, 31 Aug 2020 20:07:52 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0047.hostedemail.com [216.40.44.47]) by kanga.kvack.org (Postfix) with ESMTP id EDC596B0037 for ; Mon, 31 Aug 2020 20:07:51 -0400 (EDT) Received: from smtpin29.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id B15A0180AD80F for ; Tue, 1 Sep 2020 00:07:51 +0000 (UTC) X-FDA: 77212554342.29.game33_4b0dcf927093 Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin29.hostedemail.com (Postfix) with ESMTP id 84B8B18086CB5 for ; Tue, 1 Sep 2020 00:07:51 +0000 (UTC) X-Spam-Summary: 1,0,0,06fe45c09f1594ca,d41d8cd98f00b204,minchan.kim@gmail.com,,RULES_HIT:1:2:41:69:355:379:541:800:960:966:967:968:973:982:988:989:1260:1263:1311:1314:1345:1359:1431:1437:1515:1605:1730:1747:1777:1792:2194:2196:2198:2199:2200:2201:2376:2393:2525:2559:2566:2682:2685:2693:2859:2892:2901:2902:2911:2933:2937:2939:2942:2945:2947:2951:2954:3022:3138:3139:3140:3141:3142:3865:3866:3867:3868:3870:3871:3872:3874:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4051:4250:4321:4385:4425:4605:5007:6261:6653:6742:6743:7514:7875:7901:7903:8599:8660:8957:9025:10004:10913:11026:11473:11658:11914:12043:12296:12297:12438:12517:12519:12555:12679:12683:12783:12895:12986:13053:13141:13148:13191:13192:13229:13230:13846:13894:14096:14394:21080:21094:21323:21324:21433:21444:21451:21611:21627:21796:21939:21987:21990:30003:30036:30054:30064:30070:30075,0,RBL:209.85.214.196:@gmail.com:.lbl8.mailshell.net-62.50.0.100 66.100.201.100;04yfoowzo1ktgki83wpmmwy9s7w87ocb1f91d1aww37z51cgtj83pdah 994i7wk. X-HE-Tag: game33_4b0dcf927093 X-Filterd-Recvd-Size: 12569 Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) by imf24.hostedemail.com (Postfix) with ESMTP for ; Tue, 1 Sep 2020 00:07:50 +0000 (UTC) Received: by mail-pl1-f196.google.com with SMTP id k13so4021471plk.13 for ; Mon, 31 Aug 2020 17:07:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9v0toS4YEWMYzK02MEFlXArA+LdQ8YNff+2tLjRKFE8=; b=loncq7c6CT+AEoKDTBJeM5bSVJwnYUmCav1ptE1n063QgFNE+8rPq3hINxu9nCjGo7 0ji4wtAxZlGbmP0dRWQjrccM9maOKSJiJ++HBj0v3y3HjWsUML4N5hI6xIoV6RbsMWpY YZytYZlrEJx4zOhYOnsfRWQQd34a1vQCND3tyNficVkuj3htbAespGz6J6rVgY/KCxsa /bBIGlpkIxHTJspvAwAg8Ybq/aaY+kNfYSItb+WAo1okZTSRNY3eN3e2NWF7LjqxKxKq qD2exgxLj9A5HWX3STiTlvb0jAN9qeLAyIDW3OJYQWVDxBmPRVJthnOzPFzygTj2BnSv GCsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=9v0toS4YEWMYzK02MEFlXArA+LdQ8YNff+2tLjRKFE8=; b=rB91cW2fuxHfktr246iVCRizUq5gaRwzRvXBU93j7+bEiAmxV8Dy00uIXKTE6uPITZ iStUOXVDXZ57eJFjI7P61EX5YcVeDi4ShrmkZsnmVvkL0Dqd3UlWPhMoT+os8KqRa0P/ Azr8mHby4i/bg7dXu9iKEy8BqrDWODVfbMt1/PyW2XoYk9lWLb0OM6pq0K3TTOT0dcIz oKoeE1/OgUKQiauU+WcKIQXcCm55YNWotOaavwv4XJ0vgBvu1U6yLa1gTB8pPRCY6RJM 7yQvLChBYQn/MG4UX6WM2oa1JSsFXdqxwBIIHRX6uzLWKYur0mMi5+m83KC1L/QJWeDb PtZA== X-Gm-Message-State: AOAM530gLS+dKwa2VsTLz8rtuLJOhpjiUrZou1kse53k5fuGj0+frBKp UTQcFXXE4gAggTM2Wp0qJIU= X-Google-Smtp-Source: ABdhPJx1GFPW+c6yEJLwrJXLnT6GZ2kh1PjSdZHUxZHP4IaAqCPy2tDZk7LgzqeJ2r3EK5Jrn6rNhw== X-Received: by 2002:a17:90b:4a10:: with SMTP id kk16mr1603213pjb.203.1598918869690; Mon, 31 Aug 2020 17:07:49 -0700 (PDT) Received: from bbox-1.mtv.corp.google.com ([2620:15c:211:1:7220:84ff:fe09:5e58]) by smtp.gmail.com with ESMTPSA id k5sm769777pjq.5.2020.08.31.17.07.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Aug 2020 17:07:48 -0700 (PDT) From: Minchan Kim To: Andrew Morton Cc: LKML , Christian Brauner , linux-mm , linux-api@vger.kernel.org, oleksandr@redhat.com, Suren Baghdasaryan , Tim Murray , Sandeep Patil , Sonny Rao , Brian Geffon , Michal Hocko , Johannes Weiner , Shakeel Butt , John Dias , Joel Fernandes , Jann Horn , alexander.h.duyck@linux.intel.com, sj38.park@gmail.com, David Rientjes , Arjun Roy , Linus Torvalds , Minchan Kim , Vlastimil Babka , Jens Axboe , Daniel Colascione , Christian Brauner , Kirill Tkhai , SeongJae Park , linux-man@vger.kernel.org Subject: [PATCH v9 1/3] mm/madvise: pass mm to do_madvise Date: Mon, 31 Aug 2020 17:06:31 -0700 Message-Id: <20200901000633.1920247-2-minchan@kernel.org> X-Mailer: git-send-email 2.28.0.402.g5ffc5be6b7-goog In-Reply-To: <20200901000633.1920247-1-minchan@kernel.org> References: <20200901000633.1920247-1-minchan@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 84B8B18086CB5 X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam02 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Patch series "introduce memory hinting API for external process", v9. Now, we have MADV_PAGEOUT and MADV_COLD as madvise hinting API. With that, application could give hints to kernel what memory range are preferred to be reclaimed. However, in some platform(e.g., Android), the information required to make the hinting decision is not known to the app. Instead, it is known to a centralized userspace daemon(e.g., ActivityManagerService), and that daemon must be able to initiate reclaim on its own without any app involvement. To solve the concern, this patch introduces new syscall - process_madvise(2). Bascially, it's same with madvise(2) syscall but it has some differences. 1. It needs pidfd of target process to provide the hint 2. It supports only MADV_{COLD|PAGEOUT|MERGEABLE|UNMEREABLE} at this moment. Other hints in madvise will be opened when there are explicit requests from community to prevent unexpected bugs we couldn't support. 3. Only privileged processes can do something for other process's address space. For more detail of the new API, please see "mm: introduce external memory hinting API" description in this patchset. This patch (of 4): In upcoming patches, do_madvise will be called from external process context so we shouldn't asssume "current" is always hinted process's task_struct. Furthermore, we must not access mm_struct via task->mm, but obtain it via access_mm() once (in the following patch) and only use that pointer [1], so pass it to do_madvise() as well. Note the vma->vm_mm pointers are safe, so we can use them further down the call stack. And let's pass current->mm as arguments of do_madvise so it shouldn't change existing behavior but prepare next patch to make review easy. [vbabka@suse.cz: changelog tweak] [minchan@kernel.org: use current->mm for io_uring] Link: http://lkml.kernel.org/r/20200423145215.72666-1-minchan@kernel.org [akpm@linux-foundation.org: fix it for upstream changes] [akpm@linux-foundation.org: whoops] [rdunlap@infradead.org: add missing includes] Link: http://lkml.kernel.org/r/20200622192900.22757-1-minchan@kernel.org Link: http://lkml.kernel.org/r/20200302193630.68771-2-minchan@kernel.org Link: http://lkml.kernel.org/r/20200622192900.22757-2-minchan@kernel.org Signed-off-by: Minchan Kim Reviewed-by: Suren Baghdasaryan Reviewed-by: Vlastimil Babka Acked-by: David Rientjes Cc: Jens Axboe Cc: Jann Horn Cc: Tim Murray Cc: Daniel Colascione Cc: Sandeep Patil Cc: Sonny Rao Cc: Brian Geffon Cc: Michal Hocko Cc: Johannes Weiner Cc: Shakeel Butt Cc: John Dias Cc: Joel Fernandes Cc: Alexander Duyck Cc: SeongJae Park Cc: Christian Brauner Cc: Kirill Tkhai Cc: Oleksandr Natalenko Cc: SeongJae Park Cc: Christian Brauner Cc: --- fs/io_uring.c | 2 +- include/linux/mm.h | 2 +- mm/madvise.c | 32 ++++++++++++++++++-------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 94b9b5cf5971..cfb8003be09c 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -3823,7 +3823,7 @@ static int io_madvise(struct io_kiocb *req, bool force_nonblock) if (force_nonblock) return -EAGAIN; - ret = do_madvise(ma->addr, ma->len, ma->advice); + ret = do_madvise(current->mm, ma->addr, ma->len, ma->advice); if (ret < 0) req_set_fail_links(req); io_req_complete(req, ret); diff --git a/include/linux/mm.h b/include/linux/mm.h index 517751310dd2..a12354e63e49 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2570,7 +2570,7 @@ extern int __do_munmap(struct mm_struct *, unsigned long, size_t, struct list_head *uf, bool downgrade); extern int do_munmap(struct mm_struct *, unsigned long, size_t, struct list_head *uf); -extern int do_madvise(unsigned long start, size_t len_in, int behavior); +extern int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int behavior); #ifdef CONFIG_MMU extern int __mm_populate(unsigned long addr, unsigned long len, diff --git a/mm/madvise.c b/mm/madvise.c index 4d87b31a1576..3bf5c8261f1c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -255,6 +255,7 @@ static long madvise_willneed(struct vm_area_struct *vma, struct vm_area_struct **prev, unsigned long start, unsigned long end) { + struct mm_struct *mm = vma->vm_mm; struct file *file = vma->vm_file; loff_t offset; @@ -291,10 +292,10 @@ static long madvise_willneed(struct vm_area_struct *vma, get_file(file); offset = (loff_t)(start - vma->vm_start) + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); - mmap_read_unlock(current->mm); + mmap_read_unlock(mm); vfs_fadvise(file, offset, end - start, POSIX_FADV_WILLNEED); fput(file); - mmap_read_lock(current->mm); + mmap_read_lock(mm); return 0; } @@ -763,6 +764,8 @@ static long madvise_dontneed_free(struct vm_area_struct *vma, unsigned long start, unsigned long end, int behavior) { + struct mm_struct *mm = vma->vm_mm; + *prev = vma; if (!can_madv_lru_vma(vma)) return -EINVAL; @@ -770,8 +773,8 @@ static long madvise_dontneed_free(struct vm_area_struct *vma, if (!userfaultfd_remove(vma, start, end)) { *prev = NULL; /* mmap_lock has been dropped, prev is stale */ - mmap_read_lock(current->mm); - vma = find_vma(current->mm, start); + mmap_read_lock(mm); + vma = find_vma(mm, start); if (!vma) return -ENOMEM; if (start < vma->vm_start) { @@ -825,6 +828,7 @@ static long madvise_remove(struct vm_area_struct *vma, loff_t offset; int error; struct file *f; + struct mm_struct *mm = vma->vm_mm; *prev = NULL; /* tell sys_madvise we drop mmap_lock */ @@ -852,13 +856,13 @@ static long madvise_remove(struct vm_area_struct *vma, get_file(f); if (userfaultfd_remove(vma, start, end)) { /* mmap_lock was not released by userfaultfd_remove() */ - mmap_read_unlock(current->mm); + mmap_read_unlock(mm); } error = vfs_fallocate(f, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, end - start); fput(f); - mmap_read_lock(current->mm); + mmap_read_lock(mm); return error; } @@ -1046,7 +1050,7 @@ madvise_behavior_valid(int behavior) * -EBADF - map exists, but area maps something that isn't a file. * -EAGAIN - a kernel resource was temporarily unavailable. */ -int do_madvise(unsigned long start, size_t len_in, int behavior) +int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int behavior) { unsigned long end, tmp; struct vm_area_struct *vma, *prev; @@ -1084,10 +1088,10 @@ int do_madvise(unsigned long start, size_t len_in, int behavior) write = madvise_need_mmap_write(behavior); if (write) { - if (mmap_write_lock_killable(current->mm)) + if (mmap_write_lock_killable(mm)) return -EINTR; } else { - mmap_read_lock(current->mm); + mmap_read_lock(mm); } /* @@ -1095,7 +1099,7 @@ int do_madvise(unsigned long start, size_t len_in, int behavior) * ranges, just ignore them, but return -ENOMEM at the end. * - different from the way of handling in mlock etc. */ - vma = find_vma_prev(current->mm, start, &prev); + vma = find_vma_prev(mm, start, &prev); if (vma && start > vma->vm_start) prev = vma; @@ -1132,19 +1136,19 @@ int do_madvise(unsigned long start, size_t len_in, int behavior) if (prev) vma = prev->vm_next; else /* madvise_remove dropped mmap_lock */ - vma = find_vma(current->mm, start); + vma = find_vma(mm, start); } out: blk_finish_plug(&plug); if (write) - mmap_write_unlock(current->mm); + mmap_write_unlock(mm); else - mmap_read_unlock(current->mm); + mmap_read_unlock(mm); return error; } SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) { - return do_madvise(start, len_in, behavior); + return do_madvise(current->mm, start, len_in, behavior); } From patchwork Tue Sep 1 00:06:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Minchan Kim X-Patchwork-Id: 11747131 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AA30C109B for ; Tue, 1 Sep 2020 00:07:55 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 75FD92078B for ; Tue, 1 Sep 2020 00:07:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="e7ZLBG31" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 75FD92078B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 1C1566B0055; Mon, 31 Aug 2020 20:07:54 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 174696B005A; Mon, 31 Aug 2020 20:07:54 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 011246B005C; Mon, 31 Aug 2020 20:07:53 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0070.hostedemail.com [216.40.44.70]) by kanga.kvack.org (Postfix) with ESMTP id D98B96B0055 for ; Mon, 31 Aug 2020 20:07:53 -0400 (EDT) Received: from smtpin15.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id A67B2180AD804 for ; Tue, 1 Sep 2020 00:07:53 +0000 (UTC) X-FDA: 77212554426.15.gun44_280860427093 Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin15.hostedemail.com (Postfix) with ESMTP id 724891814B0C1 for ; Tue, 1 Sep 2020 00:07:53 +0000 (UTC) X-Spam-Summary: 1,0,0,e30b4a51298fe288,d41d8cd98f00b204,minchan.kim@gmail.com,,RULES_HIT:41:69:355:379:541:800:960:967:973:982:988:989:1260:1263:1311:1314:1345:1359:1431:1437:1515:1535:1543:1711:1730:1747:1777:1792:2198:2199:2393:2525:2559:2564:2682:2685:2859:2902:2933:2937:2939:2942:2945:2947:2951:2954:3022:3138:3139:3140:3141:3142:3354:3865:3867:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4118:4321:4605:5007:6261:6653:6742:6743:7514:7875:7903:8599:8957:9025:9592:10004:10913:11026:11658:11914:12043:12296:12297:12517:12519:12555:12679:12783:12895:12986:13846:13894:14096:14181:14394:14721:14849:21080:21094:21323:21324:21444:21451:21611:21627:21939:21990:30054:30062:30064,0,RBL:209.85.216.66:@gmail.com:.lbl8.mailshell.net-62.50.0.100 66.100.201.100;04yrfep8kkyxwi7a4fqug89bpsfxgocsgb4zb188gehot6jcheqrtjzmetp85jm.6gauef4uizxqxbfomjt4t35re1kexsobyyazohuhjy1a3iae93etxg6tjegohm8.s-lbl8.mailshell.net-223.238.255.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0, MSF:not X-HE-Tag: gun44_280860427093 X-Filterd-Recvd-Size: 7113 Received: from mail-pj1-f66.google.com (mail-pj1-f66.google.com [209.85.216.66]) by imf47.hostedemail.com (Postfix) with ESMTP for ; Tue, 1 Sep 2020 00:07:52 +0000 (UTC) Received: by mail-pj1-f66.google.com with SMTP id q1so766210pjd.1 for ; Mon, 31 Aug 2020 17:07:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DLrWB5wvlVoAHy2euEKq1/3sc+u67i1HMsT7/g7abhI=; b=e7ZLBG31SV7c0gtn6AOaBNrUKcsq5hL42yheyfoeAR9hyarTJ+VUPrehun41ljsLg9 4Tpl4o5uuXxH8bEqTgjS3qV4+7MlVUbhR3YDQojiszl5v5/0FB3KuFWnc5ut6mQ1zmBr TllJQEmbFX4u29FNsBl+OnFi8+6ToXEhYp+GolAG7n773KJi5O7g97DUg5/OWebgpRtN 1wXxR/kmTGNhdLgCupP9oN9a/0aetpbM0z6rKChNJhIzfrGuR/oJcnwhnCrBOG2fotVo O2qziM/71jC+T7i2rp5oKekaFUecZGj6lfYIUnfOApdsLiCk1Sw2yXfdfwQ5/krt5FkM Z4pA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=DLrWB5wvlVoAHy2euEKq1/3sc+u67i1HMsT7/g7abhI=; b=Qqpn8TvX8MXGkyS2p+CWiFPspVSOSWUTzG+sWBKzcYf+MX8k9uoIxee15qYFO+LEAo cfG4FPBh1aE35FzXJQ+2/UBLUyV0D+xermPZvpNch3LeRSGks7ZTV+3ssOmzkwmMnrcq 8nHU9ZJqVrXJ46uLCyMEL/hp3/iDHKNxukAnxkZVHmjVgk77xlzJRawuLgO2NBhLmcUy +c8MpIc3oD0MiwjqRQfeyQ5s2XLSw9sPd2E7MLWRKQRSFmsJIAewI0oGhvUOhJrpv8jK pisFBdMOZS0LYW/pqG9+mLHdN6fQxDKWAoiqFmpi+Q9cWQo8R3XY6Rna+KWLb5nE5Drj kq/g== X-Gm-Message-State: AOAM531aocwCAfgY4U9qGDRk9iO4o13+UtvZfEY6xlTZbnwhcHojLiAa CZsHipZoZHLcYafnxRYE8Xc= X-Google-Smtp-Source: ABdhPJw2+WxtE41OsXoPEhJhRlvcrNZ9QSecDn4o5oJjldeazK7KiDpmQOeo4Dv4MTpUiQRZkG7bLA== X-Received: by 2002:a17:90a:5a48:: with SMTP id m8mr1659813pji.181.1598918872055; Mon, 31 Aug 2020 17:07:52 -0700 (PDT) Received: from bbox-1.mtv.corp.google.com ([2620:15c:211:1:7220:84ff:fe09:5e58]) by smtp.gmail.com with ESMTPSA id k5sm769777pjq.5.2020.08.31.17.07.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Aug 2020 17:07:50 -0700 (PDT) From: Minchan Kim To: Andrew Morton Cc: LKML , Christian Brauner , linux-mm , linux-api@vger.kernel.org, oleksandr@redhat.com, Suren Baghdasaryan , Tim Murray , Sandeep Patil , Sonny Rao , Brian Geffon , Michal Hocko , Johannes Weiner , Shakeel Butt , John Dias , Joel Fernandes , Jann Horn , alexander.h.duyck@linux.intel.com, sj38.park@gmail.com, David Rientjes , Arjun Roy , Linus Torvalds , Minchan Kim , Vlastimil Babka , Jens Axboe , Daniel Colascione , Kirill Tkhai , SeongJae Park , linux-man@vger.kernel.org Subject: [PATCH v9 2/3] pid: move pidfd_get_pid() to pid.c Date: Mon, 31 Aug 2020 17:06:32 -0700 Message-Id: <20200901000633.1920247-3-minchan@kernel.org> X-Mailer: git-send-email 2.28.0.402.g5ffc5be6b7-goog In-Reply-To: <20200901000633.1920247-1-minchan@kernel.org> References: <20200901000633.1920247-1-minchan@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 724891814B0C1 X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam05 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: process_madvise syscall needs pidfd_get_pid function to translate pidfd to pid so this patch move the function to kernel/pid.c. Link: http://lkml.kernel.org/r/20200302193630.68771-5-minchan@kernel.org Link: http://lkml.kernel.org/r/20200622192900.22757-3-minchan@kernel.org Reviewed-by: Suren Baghdasaryan Suggested-by: Alexander Duyck Reviewed-by: Alexander Duyck Acked-by: Christian Brauner Reviewed-by: Vlastimil Babka Acked-by: David Rientjes Signed-off-by: Minchan Kim Cc: Jens Axboe Cc: Jann Horn Cc: Brian Geffon Cc: Daniel Colascione Cc: Joel Fernandes Cc: Johannes Weiner Cc: John Dias Cc: Kirill Tkhai Cc: Michal Hocko Cc: Oleksandr Natalenko Cc: Sandeep Patil Cc: SeongJae Park Cc: SeongJae Park Cc: Shakeel Butt Cc: Sonny Rao Cc: Tim Murray Cc: Christian Brauner Cc: --- include/linux/pid.h | 1 + kernel/exit.c | 17 ----------------- kernel/pid.c | 17 +++++++++++++++++ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/include/linux/pid.h b/include/linux/pid.h index 176d6cf80e7c..86e0e7cb7872 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -77,6 +77,7 @@ extern const struct file_operations pidfd_fops; struct file; extern struct pid *pidfd_pid(const struct file *file); +struct pid *pidfd_get_pid(unsigned int fd); static inline struct pid *get_pid(struct pid *pid) { diff --git a/kernel/exit.c b/kernel/exit.c index 733e80f334e7..62912406d74a 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1474,23 +1474,6 @@ static long do_wait(struct wait_opts *wo) return retval; } -static struct pid *pidfd_get_pid(unsigned int fd) -{ - struct fd f; - struct pid *pid; - - f = fdget(fd); - if (!f.file) - return ERR_PTR(-EBADF); - - pid = pidfd_pid(f.file); - if (!IS_ERR(pid)) - get_pid(pid); - - fdput(f); - return pid; -} - static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop, int options, struct rusage *ru) { diff --git a/kernel/pid.c b/kernel/pid.c index 2b97bedc1d9f..54e153ec6b74 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -519,6 +519,23 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns) return idr_get_next(&ns->idr, &nr); } +struct pid *pidfd_get_pid(unsigned int fd) +{ + struct fd f; + struct pid *pid; + + f = fdget(fd); + if (!f.file) + return ERR_PTR(-EBADF); + + pid = pidfd_pid(f.file); + if (!IS_ERR(pid)) + get_pid(pid); + + fdput(f); + return pid; +} + /** * pidfd_create() - Create a new pid file descriptor. * From patchwork Tue Sep 1 00:06:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Minchan Kim X-Patchwork-Id: 11747133 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A8D41109B for ; Tue, 1 Sep 2020 00:07:58 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 4ECAC2078B for ; Tue, 1 Sep 2020 00:07:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MNqNFd2t" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4ECAC2078B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id E1F306B005A; Mon, 31 Aug 2020 20:07:56 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id DF1968E0001; Mon, 31 Aug 2020 20:07:56 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id CC0596B005D; Mon, 31 Aug 2020 20:07:56 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0119.hostedemail.com [216.40.44.119]) by kanga.kvack.org (Postfix) with ESMTP id 4BDCB6B005A for ; Mon, 31 Aug 2020 20:07:56 -0400 (EDT) Received: from smtpin04.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 07070180AD804 for ; Tue, 1 Sep 2020 00:07:56 +0000 (UTC) X-FDA: 77212554552.04.pie95_530502f27093 Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin04.hostedemail.com (Postfix) with ESMTP id CEFF7800842F for ; Tue, 1 Sep 2020 00:07:55 +0000 (UTC) X-Spam-Summary: 1,0,0,6008306e56d7cc34,d41d8cd98f00b204,minchan.kim@gmail.com,,RULES_HIT:41:327:355:379:541:800:960:966:967:973:982:988:989:1042:1260:1263:1311:1314:1345:1359:1431:1437:1515:1605:1730:1747:1777:1792:1801:1981:2194:2196:2198:2199:2200:2201:2380:2393:2525:2553:2559:2568:2629:2682:2685:2689:2693:2740:2859:2892:2895:2896:2901:2902:2911:2924:2925:2926:2933:2937:2939:2942:2945:2947:2951:2954:3022:3138:3139:3140:3141:3142:3865:3866:3867:3868:3870:3871:3872:3874:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4031:4250:4321:4385:4425:4605:5007:6119:6261:6653:6691:6742:6743:7514:7875:7903:7974:8599:8603:8660:8784:8957:9025:9038:9121:10004:10226:10913:11026:11233:11473:11657:11658:11914:12043:12291:12294:12296:12297:12438:12517:12519:12555:12679:12696:12737:12783:12895:12986:13141:13142:13148:13149:13153:13161:13228:13229:13230:13255:13846:13894:14394:21080:21094:21212:21222:21323:21324:21347:21365:21433:21444:21451:21611:21627:21664:21740:21772:21789:21795:21811:2193 9:21987: X-HE-Tag: pie95_530502f27093 X-Filterd-Recvd-Size: 29103 Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) by imf18.hostedemail.com (Postfix) with ESMTP for ; Tue, 1 Sep 2020 00:07:54 +0000 (UTC) Received: by mail-pl1-f196.google.com with SMTP id x18so2818282pll.6 for ; Mon, 31 Aug 2020 17:07:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RRhlKsjH35KaXYFjcU4lt/tZ0GbvBHn7uFQg96aqkQw=; b=MNqNFd2tbZELWPHD8SqpnalRqlKX/C7mB9dtIUaAekXRyn1FW42sxVfXSxVYVbyDJs yjcu/uf6nOl7w+FQAsbsDySyTapiVXVGXeSnj3NcvKcNaYci0WG8cYMCdZvI3Okxkb5v 4CQ1ScZD5c/mBQBv+Sr7tD1LdGTVBDJ4eFgGwdTJmfk9mvl4qsOYqwVh3j3v8i2giBNU P3FLdtqziYE8vE7DYFa8Hs7g3Bi769/dIZBpfKkC68XL5jKssSgBNsYYdT6jT/SPT7pg NJAq+f0f0KnbOUmoVhyRjqz21mEZnPt3Gz3nkjNk0getL9MyD6qYLdy/VNhK31ItvWYf t9mQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=RRhlKsjH35KaXYFjcU4lt/tZ0GbvBHn7uFQg96aqkQw=; b=KQWDQhvD9Tom0X3MBMUMtNukyOsy9VR5AOAYi1CwwIdf2ZQjVM9urcURy+Fkv4xZxo qIlUNahXXW+ytyo8E0qmkqmbLW7QT6MJSNKnknYoxHdennwVtf0Kca4hWCawnoDeLjno rfPet+ziGfK6ppTQk1wmJUNeT8LRDeJW81y9F2EvAl94no+Z+cHROOIhe3TcLWusri7e Kmf2CzbhHMRKNMksEfqLBRd/4ndeSv4lSg4UsbLNrolcvkLIQb7UpIJj9FZJx+Nshj/z WDIeYCEEuTzaAQRm2wlaAxKBnO9aY5C6xLk2SsvZX/PaS09DowkhH8nQY/UEA5Xv8hTW yRHQ== X-Gm-Message-State: AOAM531cCnmUAadD0RtY8G0KVkQnFXQoV3knCUnyASdKMaM+AvFmKEwf W/Kjata79TJ2s/x1vpC9jBI= X-Google-Smtp-Source: ABdhPJzaQYg5LC/YRZ+oM8lPFv3XZZQPxe9xG4XkOxTND4xcMucifLwPe/8BuOaHenDDm2wcfwYCEA== X-Received: by 2002:a17:90a:f683:: with SMTP id cl3mr1693652pjb.124.1598918873975; Mon, 31 Aug 2020 17:07:53 -0700 (PDT) Received: from bbox-1.mtv.corp.google.com ([2620:15c:211:1:7220:84ff:fe09:5e58]) by smtp.gmail.com with ESMTPSA id k5sm769777pjq.5.2020.08.31.17.07.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Aug 2020 17:07:53 -0700 (PDT) From: Minchan Kim To: Andrew Morton Cc: LKML , Christian Brauner , linux-mm , linux-api@vger.kernel.org, oleksandr@redhat.com, Suren Baghdasaryan , Tim Murray , Sandeep Patil , Sonny Rao , Brian Geffon , Michal Hocko , Johannes Weiner , Shakeel Butt , John Dias , Joel Fernandes , Jann Horn , alexander.h.duyck@linux.intel.com, sj38.park@gmail.com, David Rientjes , Arjun Roy , Linus Torvalds , Minchan Kim , Vlastimil Babka , Christian Brauner , Daniel Colascione , Jens Axboe , Kirill Tkhai , SeongJae Park , linux-man@vger.kernel.org Subject: [PATCH v9 3/3] mm/madvise: introduce process_madvise() syscall: an external memory hinting API Date: Mon, 31 Aug 2020 17:06:33 -0700 Message-Id: <20200901000633.1920247-4-minchan@kernel.org> X-Mailer: git-send-email 2.28.0.402.g5ffc5be6b7-goog In-Reply-To: <20200901000633.1920247-1-minchan@kernel.org> References: <20200901000633.1920247-1-minchan@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: CEFF7800842F X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam03 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: There is usecase that System Management Software(SMS) want to give a memory hint like MADV_[COLD|PAGEEOUT] to other processes and in the case of Android, it is the ActivityManagerService. The information required to make the reclaim decision is not known to the app. Instead, it is known to the centralized userspace daemon(ActivityManagerService), and that daemon must be able to initiate reclaim on its own without any app involvement. To solve the issue, this patch introduces a new syscall process_madvise(2). It uses pidfd of an external process to give the hint. It also supports vector address range because Android app has thousands of vmas due to zygote so it's totally waste of CPU and power if we should call the syscall one by one for each vma.(With testing 2000-vma syscall vs 1-vector syscall, it showed 15% performance improvement. I think it would be bigger in real practice because the testing ran very cache friendly environment). Another potential use case for the vector range is to amortize the cost ofTLB shootdowns for multiple ranges when using MADV_DONTNEED; this could benefit users like TCP receive zerocopy and malloc implementations. In future, we could find more usecases for other advises so let's make it happens as API since we introduce a new syscall at this moment. With that, existing madvise(2) user could replace it with process_madvise(2) with their own pid if they want to have batch address ranges support feature. ince it could affect other process's address range, only privileged process(PTRACE_MODE_ATTACH_FSCREDS) or something else(e.g., being the same UID) gives it the right to ptrace the process could use it successfully. The flag argument is reserved for future use if we need to extend the API. I think supporting all hints madvise has/will supported/support to process_madvise is rather risky. Because we are not sure all hints make sense from external process and implementation for the hint may rely on the caller being in the current context so it could be error-prone. Thus, I just limited hints as MADV_[COLD|PAGEOUT] in this patch. If someone want to add other hints, we could hear the usecase and review it for each hint. It's safer for maintenance rather than introducing a buggy syscall but hard to fix it later. So finally, the API is as follows, ssize_t process_madvise(int pidfd, const struct iovec *iovec, unsigned long vlen, int advice, unsigned int flags); DESCRIPTION The process_madvise() system call is used to give advice or directions to the kernel about the address ranges from external process as well as local process. It provides the advice to address ranges of process described by iovec and vlen. The goal of such advice is to improve system or application performance. The pidfd selects the process referred to by the PID file descriptor specified in pidfd. (See pidofd_open(2) for further information) The pointer iovec points to an array of iovec structures, defined in as: struct iovec { void *iov_base; /* starting address */ size_t iov_len; /* number of bytes to be advised */ }; The iovec describes address ranges beginning at address(iov_base) and with size length of bytes(iov_len). The vlen represents the number of elements in iovec. The advice is indicated in the advice argument, which is one of the following at this moment if the target process specified by pidfd is external. MADV_COLD MADV_PAGEOUT Permission to provide a hint to external process is governed by a ptrace access mode PTRACE_MODE_ATTACH_FSCREDS check; see ptrace(2). The process_madvise supports every advice madvise(2) has if target process is in same thread group with calling process so user could use process_madvise(2) to extend existing madvise(2) to support vector address ranges. RETURN VALUE On success, process_madvise() returns the number of bytes advised. This return value may be less than the total number of requested bytes, if an error occurred. The caller should check return value to determine whether a partial advice occurred. FAQ: Q.1 - Why does any external entity have better knowledge? Quote from Sandeep "For Android, every application (including the special SystemServer) are forked from Zygote. The reason of course is to share as many libraries and classes between the two as possible to benefit from the preloading during boot. After applications start, (almost) all of the APIs end up calling into this SystemServer process over IPC (binder) and back to the application. In a fully running system, the SystemServer monitors every single process periodically to calculate their PSS / RSS and also decides which process is "important" to the user for interactivity. So, because of how these processes start _and_ the fact that the SystemServer is looping to monitor each process, it does tend to *know* which address range of the application is not used / useful. Besides, we can never rely on applications to clean things up themselves. We've had the "hey app1, the system is low on memory, please trim your memory usage down" notifications for a long time[1]. They rely on applications honoring the broadcasts and very few do. So, if we want to avoid the inevitable killing of the application and restarting it, some way to be able to tell the OS about unimportant memory in these applications will be useful. - ssp Q.2 - How to guarantee the race(i.e., object validation) between when giving a hint from an external process and get the hint from the target process? process_madvise operates on the target process's address space as it exists at the instant that process_madvise is called. If the space target process can run between the time the process_madvise process inspects the target process address space and the time that process_madvise is actually called, process_madvise may operate on memory regions that the calling process does not expect. It's the responsibility of the process calling process_madvise to close this race condition. For example, the calling process can suspend the target process with ptrace, SIGSTOP, or the freezer cgroup so that it doesn't have an opportunity to change its own address space before process_madvise is called. Another option is to operate on memory regions that the caller knows a priori will be unchanged in the target process. Yet another option is to accept the race for certain process_madvise calls after reasoning that mistargeting will do no harm. The suggested API itself does not provide synchronization. It also apply other APIs like move_pages, process_vm_write. The race isn't really a problem though. Why is it so wrong to require that callers do their own synchronization in some manner? Nobody objects to write(2) merely because it's possible for two processes to open the same file and clobber each other's writes --- instead, we tell people to use flock or something. Think about mmap. It never guarantees newly allocated address space is still valid when the user tries to access it because other threads could unmap the memory right before. That's where we need synchronization by using other API or design from userside. It shouldn't be part of API itself. If someone needs more fine-grained synchronization rather than process level, there were two ideas suggested - cookie[2] and anon-fd[3]. Both are applicable via using last reserved argument of the API but I don't think it's necessary right now since we have already ways to prevent the race so don't want to add additional complexity with more fine-grained optimization model. To make the API extend, it reserved an unsigned long as last argument so we could support it in future if someone really needs it. Q.3 - Why doesn't ptrace work? Injecting an madvise in the target process using ptrace would not work for us because such injected madvise would have to be executed by the target process, which means that process would have to be runnable and that creates the risk of the abovementioned race and hinting a wrong VMA. Furthermore, we want to act the hint in caller's context, not the callee's, because the callee is usually limited in cpuset/cgroups or even freezed state so they can't act by themselves quick enough, which causes more thrashing/kill. It doesn't work if the target process are ptraced(e.g., strace, debugger, minidump) because a process can have at most one ptracer. [1] https://developer.android.com/topic/performance/memory" [2] process_getinfo for getting the cookie which is updated whenever vma of process address layout are changed - Daniel Colascione - https://lore.kernel.org/lkml/20190520035254.57579-1-minchan@kernel.org/T/#m7694416fd179b2066a2c62b5b139b14e3894e224 [3] anonymous fd which is used for the object(i.e., address range) validation - Michal Hocko - https://lore.kernel.org/lkml/20200120112722.GY18451@dhcp22.suse.cz/ [minchan@kernel.org: fix process_madvise build break for arm64] Link: http://lkml.kernel.org/r/20200303145756.GA219683@google.com [minchan@kernel.org: fix build error for mips of process_madvise] Link: http://lkml.kernel.org/r/20200508052517.GA197378@google.com [akpm@linux-foundation.org: fix patch ordering issue] [akpm@linux-foundation.org: fix arm64 whoops] Link: http://lkml.kernel.org/r/20200302193630.68771-3-minchan@kernel.org Link: http://lkml.kernel.org/r/20200508183320.GA125527@google.com Link: http://lkml.kernel.org/r/20200622192900.22757-4-minchan@kernel.org Reviewed-by: Suren Baghdasaryan Reviewed-by: Vlastimil Babka Acked-by: David Rientjes Signed-off-by: Minchan Kim Cc: Alexander Duyck Cc: Brian Geffon Cc: Christian Brauner Cc: Daniel Colascione Cc: Jann Horn Cc: Jens Axboe Cc: Joel Fernandes Cc: Johannes Weiner Cc: John Dias Cc: Kirill Tkhai Cc: Michal Hocko Cc: Oleksandr Natalenko Cc: Sandeep Patil Cc: SeongJae Park Cc: SeongJae Park Cc: Shakeel Butt Cc: Sonny Rao Cc: Tim Murray Cc: Christian Brauner Cc: Reviewed-by: Suren Baghdasaryan Reviewed-by: Vlastimil Babka Acked-by: David Rientjes Signed-off-by: Minchan Kim Signed-off-by: Minchan Kim Signed-off-by: Eric Dumazet Signed-off-by: Minchan Kim --- arch/alpha/kernel/syscalls/syscall.tbl | 1 + arch/arm/tools/syscall.tbl | 1 + arch/arm64/include/asm/unistd.h | 2 +- arch/arm64/include/asm/unistd32.h | 2 + arch/ia64/kernel/syscalls/syscall.tbl | 1 + arch/m68k/kernel/syscalls/syscall.tbl | 1 + arch/microblaze/kernel/syscalls/syscall.tbl | 1 + arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + arch/mips/kernel/syscalls/syscall_o32.tbl | 1 + arch/parisc/kernel/syscalls/syscall.tbl | 1 + arch/powerpc/kernel/syscalls/syscall.tbl | 1 + arch/s390/kernel/syscalls/syscall.tbl | 1 + arch/sh/kernel/syscalls/syscall.tbl | 1 + arch/sparc/kernel/syscalls/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + arch/xtensa/kernel/syscalls/syscall.tbl | 1 + include/linux/syscalls.h | 2 + include/uapi/asm-generic/unistd.h | 4 +- kernel/sys_ni.c | 1 + mm/madvise.c | 109 ++++++++++++++++++++ 21 files changed, 133 insertions(+), 2 deletions(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index 805d2ca50b4d..160cb7c46db0 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -480,3 +480,4 @@ 548 common pidfd_getfd sys_pidfd_getfd 549 common faccessat2 sys_faccessat2 550 common watch_mount sys_watch_mount +551 common process_madvise sys_process_madvise diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 974d25b28316..3d3a3fe6931e 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -454,3 +454,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index b3b2019f8d16..86a9d7b3eabe 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -38,7 +38,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 441 +#define __NR_compat_syscalls 442 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 30e0cb686071..ef98f5e2300c 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -889,6 +889,8 @@ __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd) __SYSCALL(__NR_faccessat2, sys_faccessat2) #define __NR_watch_mount 440 __SYSCALL(__NR_watch_mount, sys_watch_mount) +#define __NR_watch_mount 441 +__SYSCALL(__NR_process_madvise, sys_process_madvise) /* * Please add new compat syscalls above this comment and update diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index f27af175bc75..7e30a024062b 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -361,3 +361,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index 25db9c8e412e..3b237088ef9c 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -440,3 +440,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index e74adc19b288..fbbe9ad06f14 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -446,3 +446,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 4f51890c8eeb..05513235b7a9 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -379,3 +379,4 @@ 438 n32 pidfd_getfd sys_pidfd_getfd 439 n32 faccessat2 sys_faccessat2 440 n32 watch_mount sys_watch_mount +441 n32 process_madvise sys_process_madvise diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 608922cddddb..f3d1fb1c5626 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -428,3 +428,4 @@ 438 o32 pidfd_getfd sys_pidfd_getfd 439 o32 faccessat2 sys_faccessat2 440 o32 watch_mount sys_watch_mount +441 o32 process_madvise sys_process_madvise diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 714e5359e259..94d1f465f82a 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -438,3 +438,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 07c1ab563b78..1bd3de01b87f 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -530,3 +530,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 957a776b8646..9ed96b429ba9 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -443,3 +443,4 @@ 438 common pidfd_getfd sys_pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise sys_process_madvise diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index 6de03fe8c589..17147784ac47 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -443,3 +443,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index a14b56b56dbd..320f49cfd1e8 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -486,3 +486,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 54560f3035f7..805cd33d483c 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -445,3 +445,4 @@ 438 i386 pidfd_getfd sys_pidfd_getfd 439 i386 faccessat2 sys_faccessat2 440 i386 watch_mount sys_watch_mount +441 i386 process_madvise sys_process_madvise diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index f08845dbfaa1..1dfad1dd7ec8 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -362,6 +362,7 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index de025a07d958..3e65f24adfe1 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -411,3 +411,4 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common watch_mount sys_watch_mount +441 common process_madvise sys_process_madvise diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 2ba46d811fe8..0c486cf267cf 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -879,6 +879,8 @@ asmlinkage long sys_munlockall(void); asmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char __user * vec); asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); +asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec, + unsigned long vlen, int behavior, unsigned int flags); asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags); diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index b9285f261a9e..e678a93f55ec 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -861,9 +861,11 @@ __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd) __SYSCALL(__NR_faccessat2, sys_faccessat2) #define __NR_watch_mount 440 __SYSCALL(__NR_watch_mount, sys_watch_mount) +#define __NR_watch_mount 441 +__SYSCALL(__NR_process_madvise, sys_process_madvise) #undef __NR_syscalls -#define __NR_syscalls 441 +#define __NR_syscalls 442 /* * 32 bit systems traditionally used different diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 66e05c695842..10c32a2f4864 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -283,6 +283,7 @@ COND_SYSCALL(mlockall); COND_SYSCALL(munlockall); COND_SYSCALL(mincore); COND_SYSCALL(madvise); +COND_SYSCALL(process_madvise); COND_SYSCALL(remap_file_pages); COND_SYSCALL(mbind); COND_SYSCALL_COMPAT(mbind); diff --git a/mm/madvise.c b/mm/madvise.c index 3bf5c8261f1c..54ea958a6f3b 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -989,6 +990,18 @@ madvise_behavior_valid(int behavior) } } +static bool +process_madvise_behavior_valid(int behavior) +{ + switch (behavior) { + case MADV_COLD: + case MADV_PAGEOUT: + return true; + default: + return false; + } +} + /* * The madvise(2) system call. * @@ -1036,6 +1049,11 @@ madvise_behavior_valid(int behavior) * MADV_DONTDUMP - the application wants to prevent pages in the given range * from being included in its core dump. * MADV_DODUMP - cancel MADV_DONTDUMP: no longer exclude from core dump. + * MADV_COLD - the application is not expected to use this memory soon, + * deactivate pages in this range so that they can be reclaimed + * easily if memory pressure hanppens. + * MADV_PAGEOUT - the application is not expected to use this memory soon, + * page out the pages in this range immediately. * * return values: * zero - success @@ -1152,3 +1170,94 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) { return do_madvise(current->mm, start, len_in, behavior); } + +static int process_madvise_vec(struct mm_struct *mm, struct iov_iter *iter, int behavior) +{ + struct iovec iovec; + int ret = 0; + + while (iov_iter_count(iter)) { + iovec = iov_iter_iovec(iter); + ret = do_madvise(mm, (unsigned long)iovec.iov_base, iovec.iov_len, behavior); + if (ret < 0) + break; + iov_iter_advance(iter, iovec.iov_len); + } + + return ret; +} + +static ssize_t do_process_madvise(int pidfd, struct iov_iter *iter, + int behavior, unsigned int flags) +{ + ssize_t ret; + struct pid *pid; + struct task_struct *task; + struct mm_struct *mm; + size_t total_len = iov_iter_count(iter); + + if (flags != 0) + return -EINVAL; + + pid = pidfd_get_pid(pidfd); + if (IS_ERR(pid)) + return PTR_ERR(pid); + + task = get_pid_task(pid, PIDTYPE_PID); + if (!task) { + ret = -ESRCH; + goto put_pid; + } + + if (task->mm != current->mm && + !process_madvise_behavior_valid(behavior)) { + ret = -EINVAL; + goto release_task; + } + + mm = mm_access(task, PTRACE_MODE_ATTACH_FSCREDS); + if (IS_ERR_OR_NULL(mm)) { + ret = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; + goto release_task; + } + + ret = process_madvise_vec(mm, iter, behavior); + if (ret >= 0) + ret = total_len - iov_iter_count(iter); + + mmput(mm); +release_task: + put_task_struct(task); +put_pid: + put_pid(pid); + return ret; +} + +static inline int madv_import_iovec(int type, const struct iovec __user *uvec, unsigned int nr_segs, + unsigned int fast_segs, struct iovec **iov, struct iov_iter *i) +{ +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + return compat_import_iovec(type, (struct compat_iovec __user *)uvec, nr_segs, + fast_segs, iov, i); +#endif + + return import_iovec(type, uvec, nr_segs, fast_segs, iov, i); +} + +SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec, + unsigned long, vlen, int, behavior, unsigned int, flags) +{ + ssize_t ret; + struct iovec iovstack[UIO_FASTIOV]; + struct iovec *iov = iovstack; + struct iov_iter iter; + + ret = madv_import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); + if (ret < 0) + return ret; + + ret = do_process_madvise(pidfd, &iter, behavior, flags); + kfree(iov); + return ret; +}