From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933837AbdBQL00 (ORCPT ); Fri, 17 Feb 2017 06:26:26 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:45773 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933741AbdBQL0X (ORCPT ); Fri, 17 Feb 2017 06:26:23 -0500 From: Anshuman Khandual To: linux-kernel@vger.kernel.org, linux-mm@kvack.org Cc: mhocko@suse.com, vbabka@suse.cz, mgorman@suse.de, minchan@kernel.org, aneesh.kumar@linux.vnet.ibm.com, bsingharora@gmail.com, srikar@linux.vnet.ibm.com, haren@linux.vnet.ibm.com, jglisse@redhat.com, dave.hansen@intel.com, dan.j.williams@intel.com, zi.yan@cs.rutgers.edu Subject: [PATCH 3/6] mm/migrate: Add copy_pages_mthread function Date: Fri, 17 Feb 2017 16:54:50 +0530 X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170217112453.307-1-khandual@linux.vnet.ibm.com> References: <20170217112453.307-1-khandual@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17021711-0016-0000-0000-0000021AD195 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17021711-0017-0000-0000-0000066F09E4 Message-Id: <20170217112453.307-4-khandual@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2017-02-17_09:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=3 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1702170108 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Zi Yan This change adds a new function copy_pages_mthread to enable multi threaded page copy which can be utilized during migration. This function splits the page copy request into multiple threads which will handle individual chunk and send them as jobs to system_highpri_wq work queue. Signed-off-by: Zi Yan Signed-off-by: Anshuman Khandual --- include/linux/highmem.h | 2 ++ mm/Makefile | 2 ++ mm/copy_pages_mthread.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 mm/copy_pages_mthread.c diff --git a/include/linux/highmem.h b/include/linux/highmem.h index bb3f329..e1f4f1b 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -236,6 +236,8 @@ static inline void copy_user_highpage(struct page *to, struct page *from, #endif +int copy_pages_mthread(struct page *to, struct page *from, int nr_pages); + static inline void copy_highpage(struct page *to, struct page *from) { char *vfrom, *vto; diff --git a/mm/Makefile b/mm/Makefile index 295bd7a..cc27e76 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -41,6 +41,8 @@ obj-y := filemap.o mempool.o oom_kill.o \ obj-y += init-mm.o +obj-y += copy_pages_mthread.o + ifdef CONFIG_NO_BOOTMEM obj-y += nobootmem.o else diff --git a/mm/copy_pages_mthread.c b/mm/copy_pages_mthread.c new file mode 100644 index 0000000..9ad2ef6 --- /dev/null +++ b/mm/copy_pages_mthread.c @@ -0,0 +1,87 @@ +/* + * This implements parallel page copy function through multi + * threaded work queues. + * + * Copyright (C) Zi Yan , Nov 2016 + * + * Licensed under the terms of the GNU GPL, version 2. + */ +#include +#include +#include +#include + +/* + * nr_copythreads can be the highest number of threads for given + * node on any architecture. The actual number of copy threads + * will be limited by the cpumask weight of the target node. + */ +unsigned int nr_copythreads = 8; + +struct copy_info { + struct work_struct copy_work; + char *to; + char *from; + unsigned long chunk_size; +}; + +static void copy_pages(char *vto, char *vfrom, unsigned long size) +{ + memcpy(vto, vfrom, size); +} + +static void copythread(struct work_struct *work) +{ + struct copy_info *info = (struct copy_info *) work; + + copy_pages(info->to, info->from, info->chunk_size); +} + +int copy_pages_mthread(struct page *to, struct page *from, int nr_pages) +{ + struct cpumask *cpumask; + struct copy_info *work_items; + char *vto, *vfrom; + unsigned long i, cthreads, cpu, node, chunk_size; + int cpu_id_list[32] = {0}; + + node = page_to_nid(to); + cpumask = cpumask_of_node(node); + cthreads = nr_copythreads; + cthreads = min_t(unsigned int, cthreads, cpumask_weight(cpumask)); + cthreads = (cthreads / 2) * 2; + work_items = kcalloc(cthreads, sizeof(struct copy_info), GFP_KERNEL); + if (!work_items) + return -ENOMEM; + + i = 0; + for_each_cpu(cpu, cpumask) { + if (i >= cthreads) + break; + cpu_id_list[i] = cpu; + ++i; + } + + vfrom = kmap(from); + vto = kmap(to); + chunk_size = PAGE_SIZE * nr_pages / cthreads; + + for (i = 0; i < cthreads; ++i) { + INIT_WORK((struct work_struct *) &work_items[i], copythread); + + work_items[i].to = vto + i * chunk_size; + work_items[i].from = vfrom + i * chunk_size; + work_items[i].chunk_size = chunk_size; + + queue_work_on(cpu_id_list[i], system_highpri_wq, + (struct work_struct *) &work_items[i]); + } + + for (i = 0; i < cthreads; ++i) + flush_work((struct work_struct *) &work_items[i]); + + kunmap(to); + kunmap(from); + kfree(work_items); + return 0; +} -- 2.9.3