From patchwork Thu Apr 27 00:08:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Yznaga X-Patchwork-Id: 13225029 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7DEAC7618E for ; Thu, 27 Apr 2023 00:09:46 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id EF10C6B0072; Wed, 26 Apr 2023 20:09:45 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id EA0636B0075; Wed, 26 Apr 2023 20:09:45 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D41496B0074; Wed, 26 Apr 2023 20:09:45 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id C027F6B0071 for ; Wed, 26 Apr 2023 20:09:45 -0400 (EDT) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 92D58160418 for ; Thu, 27 Apr 2023 00:09:45 +0000 (UTC) X-FDA: 80725237530.08.95807FC Received: from mx0a-00069f02.pphosted.com (mx0a-00069f02.pphosted.com [205.220.165.32]) by imf13.hostedemail.com (Postfix) with ESMTP id 86C4320014 for ; Thu, 27 Apr 2023 00:09:43 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=oracle.com header.s=corp-2023-03-30 header.b=TxlrwQ0h; dmarc=pass (policy=none) header.from=oracle.com; spf=pass (imf13.hostedemail.com: domain of anthony.yznaga@oracle.com designates 205.220.165.32 as permitted sender) smtp.mailfrom=anthony.yznaga@oracle.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1682554183; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references:dkim-signature; bh=2ukFf+zRaNRmI8y9b//d4HHLWejv/e/RSSnUHKNUOb0=; b=qvJMQa6ADBieDXO5JdqBPLJDmy7C3dMPS5M0SkgNqWxrEJil12utIm/xH7quBKv9B2LUef bluUsMBJUnzY98XMEI74moj1MljpL1415UqVetDYPWKWQXeWGoTq1faw/IqwC071kxJoW7 I6KCWra3i7zAgRxV3SBJI0iVegKkuV0= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=pass header.d=oracle.com header.s=corp-2023-03-30 header.b=TxlrwQ0h; dmarc=pass (policy=none) header.from=oracle.com; spf=pass (imf13.hostedemail.com: domain of anthony.yznaga@oracle.com designates 205.220.165.32 as permitted sender) smtp.mailfrom=anthony.yznaga@oracle.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1682554183; a=rsa-sha256; cv=none; b=YPksKJLBuhFMDl3vh0BNZmAdrFxItp07nJjHpH17681tgqqjrPDkihP9xB3WL7voOb4+Dr dw9CBPl8p6fkR/8xn6Cc4k45idcSZm9Qk5O6c5Z5Q9Rw8HBJIX6Iu/tQD/Q6EVfZO/bAuh 4PtwWjtX+pS1VqzXhBd9MwBU28ya4bk= Received: from pps.filterd (m0246627.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 33QGxEtw025349; Thu, 27 Apr 2023 00:09:09 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2023-03-30; bh=2ukFf+zRaNRmI8y9b//d4HHLWejv/e/RSSnUHKNUOb0=; b=TxlrwQ0h7qFCJaeuzgzyEU0pAR/9XxEhbPIoeg6wR+uexwlVY+B8YNO/biu1qWN7dWsN zWja6dGffqrU7IioURUI0OMKQZQ9tuPCh7XG67qZectGRQhDmBVm+QZ5BEeNmOZgOdVi nwIybKeQicAO1qnGABVzNxIV9c/kc+TFYGvW3OrDaKffhxCBcJ2xvnKxbTw+ksNL93ET +3oK/5n13QLSew1loC2CozejsH8uV5iwonsq7XVCCgHaF7rHjDHPkQxkLHPsi67hbOyd YXklKe+yThp4IMn+e8XDiW13KH4eGybP1zScjsIW4e6WZfTZ9OYxWFtBQe1eEa6RptVa Hg== Received: from phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta01.appoci.oracle.com [138.1.114.2]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3q46622txu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 27 Apr 2023 00:09:08 +0000 Received: from pps.filterd (phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 33QLGcu0007340; Thu, 27 Apr 2023 00:09:07 GMT Received: from pps.reinject (localhost [127.0.0.1]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3q4618mpab-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 27 Apr 2023 00:09:07 +0000 Received: from phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 33R0938Q013888; Thu, 27 Apr 2023 00:09:07 GMT Received: from ca-qasparc-x86-2.us.oracle.com (ca-qasparc-x86-2.us.oracle.com [10.147.24.103]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTP id 3q4618mp42-3; Thu, 27 Apr 2023 00:09:06 +0000 From: Anthony Yznaga To: linux-mm@kvack.org, linux-kernel@vger.kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, x86@kernel.org, hpa@zytor.com, dave.hansen@linux.intel.com, luto@kernel.org, peterz@infradead.org, rppt@kernel.org, akpm@linux-foundation.org, ebiederm@xmission.com, keescook@chromium.org, graf@amazon.com, jason.zeng@intel.com, lei.l.li@intel.com, steven.sistare@oracle.com, fam.zheng@bytedance.com, mgalaxy@akamai.com, kexec@lists.infradead.org Subject: [RFC v3 02/21] mm: PKRAM: implement node load and save functions Date: Wed, 26 Apr 2023 17:08:38 -0700 Message-Id: <1682554137-13938-3-git-send-email-anthony.yznaga@oracle.com> X-Mailer: git-send-email 1.9.4 In-Reply-To: <1682554137-13938-1-git-send-email-anthony.yznaga@oracle.com> References: <1682554137-13938-1-git-send-email-anthony.yznaga@oracle.com> X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.942,Hydra:6.0.573,FMLib:17.11.170.22 definitions=2023-04-26_10,2023-04-26_03,2023-02-09_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 phishscore=0 bulkscore=0 mlxlogscore=999 malwarescore=0 mlxscore=0 spamscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2303200000 definitions=main-2304270000 X-Proofpoint-ORIG-GUID: BhiXjpaVT-IHUNxaCSxCFNS9jekWEvq_ X-Proofpoint-GUID: BhiXjpaVT-IHUNxaCSxCFNS9jekWEvq_ X-Rspam-User: X-Rspamd-Server: rspam02 X-Rspamd-Queue-Id: 86C4320014 X-Stat-Signature: c3ap811hmg4ytcrmbwedpjmjk4b8rku4 X-HE-Tag: 1682554183-746766 X-HE-Meta: U2FsdGVkX18v7CmNO99NAmsNcrwyyJBas1QFhv6a04H6T0Xcmy2e2yx3ae2VsHwqZLs/VVZKjD5HzPn1Br/IWkuQJiJdm8zR4H8Hmso4Z2QbtU6NxRhIloofmsxF4B1Ghjmy6eLiDJ2PdrPQtkQZHkJ8guYpr9Xv878tRh/6drbxbPciQLzgMnT7TTFqeYT6D1rmOUX/NwQO7Wj3tRJ3qcuPbo3LL+VhRamR/jF8tIOBxd4ASpe+lb377VJ4C0OWPBtYqDDRsFjiOyKVNz9CFBoaLoKAjjalXd4JOjSzasPaWUtxQGmjlyX215GLn6Oxneeas4rJ/ItJHps8ufGqUkwW1T6csKSp8FDyDcFPkaFyZrGGfglpLlFazNUEKMo9vdTTk4niZW4U+KPnlqxCUyQCH0GM86qR6dlXWXhft9zr+HQDzY/GbBpj3YeaHvpM3mCfIGX48cx5CgBFmfndY8iievxgQ/ivPhePN4G63z1w1T5jvGxJkzvrs95X1+g2PCS5enRNwFwkY2H5PJ5vQi1k77/Hl0we3MgRevemwgqU5hOPU5j0RH4FvoTKLoczATNFgTMkvW8UuNcsq10hULUveFBstG8vE26BXbZ4mJ6FfTpx/MhjHXfrp9uVU7/+ZEwjts3/5kAqyjL1SIu7QaMS1jp/VmXfmYxHdlqewt6uy1d3BSK/6g78CokaAbTQ3X6bapDsZ0sDxLlhZqzVCiPrtrGiP7SeIZ+eYT9TtI9c+SQC89DDZZeHDM/A0OPvkRFRz0N4/lUIMSyC9sJ/Q9iYt/CDdYbYDFYucvtRRIfZnutKxP66ZbhY+ccc0TvUqiQEIqlj8d30e7BHvsa0amyDtZMst13zYK7LpDgcppBpsvFaEQEEF3X+wOledlXLqsGdfeq/cpg5YRaDd88Z36GyFqUM1JkNZPlyXT6wbxsUKxhJ7qv6rWj7Q8VyVjNoCsahyLzf5z/iPmrbFWG StxC/7cv wx1IsZqUkJ4Fvhd4cISsD12ZEXnOJArrSJJYqQLvYiOyC+1cp+vFLiFS5EFN3SaZR/xZIQFfQq6EaSlQA8rBuQd8ZIkfrw1n8vuHKWgbK5fN0FwWqEbDAvyvuS6a0dt+3VPoAJXTmsx2mvQB+W/udxwMjsdj3Nnvve2He 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: Preserved memory is divided into nodes which can be saved and loaded independently of each other. PKRAM nodes are kept on a list and identified by unique names. Whenever a save operation is initiated by calling pkram_prepare_save(), a new node is created and linked to the list. When the save operation has been committed by calling pkram_finish_save(), the node becomes loadable. A load operation can be then initiated by calling pkram_prepare_load() which deletes the node from the list and prepares the corresponding stream for loading data from it. After the load has been finished, the pkram_finish_load() function must be called to free the node. Nodes are also deleted when a save operation is discarded, i.e. pkram_discard_save() is called instead of pkram_finish_save(). Originally-by: Vladimir Davydov Signed-off-by: Anthony Yznaga --- include/linux/pkram.h | 8 ++- mm/pkram.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 149 insertions(+), 6 deletions(-) diff --git a/include/linux/pkram.h b/include/linux/pkram.h index 57b8db4229a4..8def9017b16a 100644 --- a/include/linux/pkram.h +++ b/include/linux/pkram.h @@ -6,6 +6,8 @@ #include #include +struct pkram_node; + /** * enum pkram_data_flags - definition of data types contained in a pkram obj * @PKRAM_DATA_none: No data types configured @@ -14,7 +16,11 @@ enum pkram_data_flags { PKRAM_DATA_none = 0x0, /* No data types configured */ }; -struct pkram_stream; +struct pkram_stream { + gfp_t gfp_mask; + struct pkram_node *node; +}; + struct pkram_access; #define PKRAM_NAME_MAX 256 /* including nul */ diff --git a/mm/pkram.c b/mm/pkram.c index 421de8211e05..bbfd8df0874e 100644 --- a/mm/pkram.c +++ b/mm/pkram.c @@ -2,16 +2,85 @@ #include #include #include +#include #include +#include #include +#include #include +/* + * Preserved memory is divided into nodes that can be saved or loaded + * independently of each other. The nodes are identified by unique name + * strings. + * + * The structure occupies a memory page. + */ +struct pkram_node { + __u32 flags; + + __u8 name[PKRAM_NAME_MAX]; +}; + +#define PKRAM_SAVE 1 +#define PKRAM_LOAD 2 +#define PKRAM_ACCMODE_MASK 3 + +static LIST_HEAD(pkram_nodes); /* linked through page::lru */ +static DEFINE_MUTEX(pkram_mutex); /* serializes open/close */ + +static inline struct page *pkram_alloc_page(gfp_t gfp_mask) +{ + return alloc_page(gfp_mask); +} + +static inline void pkram_free_page(void *addr) +{ + free_page((unsigned long)addr); +} + +static inline void pkram_insert_node(struct pkram_node *node) +{ + list_add(&virt_to_page(node)->lru, &pkram_nodes); +} + +static inline void pkram_delete_node(struct pkram_node *node) +{ + list_del(&virt_to_page(node)->lru); +} + +static struct pkram_node *pkram_find_node(const char *name) +{ + struct page *page; + struct pkram_node *node; + + list_for_each_entry(page, &pkram_nodes, lru) { + node = page_address(page); + if (strcmp(node->name, name) == 0) + return node; + } + return NULL; +} + +static void pkram_stream_init(struct pkram_stream *ps, + struct pkram_node *node, gfp_t gfp_mask) +{ + memset(ps, 0, sizeof(*ps)); + ps->gfp_mask = gfp_mask; + ps->node = node; +} + /** * Create a preserved memory node with name @name and initialize stream @ps * for saving data to it. * * @gfp_mask specifies the memory allocation mask to be used when saving data. * + * Error values: + * %ENAMETOOLONG: name len >= PKRAM_NAME_MAX + * %ENOMEM: insufficient memory available + * %EEXIST: node with specified name already exists + * * Returns 0 on success, -errno on failure. * * After the save has finished, pkram_finish_save() (or pkram_discard_save() in @@ -19,7 +88,34 @@ */ int pkram_prepare_save(struct pkram_stream *ps, const char *name, gfp_t gfp_mask) { - return -EINVAL; + struct page *page; + struct pkram_node *node; + int err = 0; + + if (strlen(name) >= PKRAM_NAME_MAX) + return -ENAMETOOLONG; + + page = pkram_alloc_page(gfp_mask | __GFP_ZERO); + if (!page) + return -ENOMEM; + node = page_address(page); + + node->flags = PKRAM_SAVE; + strcpy(node->name, name); + + mutex_lock(&pkram_mutex); + if (!pkram_find_node(name)) + pkram_insert_node(node); + else + err = -EEXIST; + mutex_unlock(&pkram_mutex); + if (err) { + pkram_free_page(node); + return err; + } + + pkram_stream_init(ps, node, gfp_mask); + return 0; } /** @@ -50,7 +146,11 @@ void pkram_finish_save_obj(struct pkram_stream *ps) */ void pkram_finish_save(struct pkram_stream *ps) { - WARN_ON_ONCE(1); + struct pkram_node *node = ps->node; + + BUG_ON((node->flags & PKRAM_ACCMODE_MASK) != PKRAM_SAVE); + + node->flags &= ~PKRAM_ACCMODE_MASK; } /** @@ -60,7 +160,15 @@ void pkram_finish_save(struct pkram_stream *ps) */ void pkram_discard_save(struct pkram_stream *ps) { - WARN_ON_ONCE(1); + struct pkram_node *node = ps->node; + + BUG_ON((node->flags & PKRAM_ACCMODE_MASK) != PKRAM_SAVE); + + mutex_lock(&pkram_mutex); + pkram_delete_node(node); + mutex_unlock(&pkram_mutex); + + pkram_free_page(node); } /** @@ -69,11 +177,36 @@ void pkram_discard_save(struct pkram_stream *ps) * * Returns 0 on success, -errno on failure. * + * Error values: + * %ENOENT: node with specified name does not exist + * %EBUSY: save to required node has not finished yet + * * After the load has finished, pkram_finish_load() is to be called. */ int pkram_prepare_load(struct pkram_stream *ps, const char *name) { - return -EINVAL; + struct pkram_node *node; + int err = 0; + + mutex_lock(&pkram_mutex); + node = pkram_find_node(name); + if (!node) { + err = -ENOENT; + goto out_unlock; + } + if (node->flags & PKRAM_ACCMODE_MASK) { + err = -EBUSY; + goto out_unlock; + } + pkram_delete_node(node); +out_unlock: + mutex_unlock(&pkram_mutex); + if (err) + return err; + + node->flags |= PKRAM_LOAD; + pkram_stream_init(ps, node, 0); + return 0; } /** @@ -106,7 +239,11 @@ void pkram_finish_load_obj(struct pkram_stream *ps) */ void pkram_finish_load(struct pkram_stream *ps) { - WARN_ON_ONCE(1); + struct pkram_node *node = ps->node; + + BUG_ON((node->flags & PKRAM_ACCMODE_MASK) != PKRAM_LOAD); + + pkram_free_page(node); } /**