Received: by 2002:a05:6a10:f3d0:0:0:0:0 with SMTP id a16csp4220645pxv; Tue, 29 Jun 2021 01:42:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxhVn/V2eI1gJqYUpcAFFn8BBzGAIn5FelR2QCVjUgh4Lq64p3W/t9UfLe+stvoONTyyMIz X-Received: by 2002:a05:6e02:1064:: with SMTP id q4mr21485607ilj.127.1624956176328; Tue, 29 Jun 2021 01:42:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1624956176; cv=none; d=google.com; s=arc-20160816; b=LpO+WvEpsPd1iSTz3z4x8NL78DVNcL9lX0dU9ptbOpngz2ftb/vZAwn9Hm0qAADLx5 Dh24kuw0DsxOmCZw7egWvsaXqWbiPVuOuG8HnX364j4mZcL7SzC70eZN5tC+wlkba4zY tzU9ps9ox1sChVN05LJpQZU2V99cNUf4i7fkl8faOZiAe7ddBEwlqN+EZ3yPavURUyM/ 5dYj8yHN3stOmaQu/mDRAwxSUKAIjOokiS8BdM+kmm3FHgNkTuvCzn3uKHDLnN6LlGZO 2+cURzzTNNKNejoFiuGRlXBqffDoP81J8wPmFLPYCdgzQx/2DsNdw5wBWQqCJ/PLES2R O7Ug== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=uc98qL4WXfUJt8/UtCEC8HUJcfLHvZ442Ix3mkiRNIE=; b=RfI8GVWrxTXSa3Cy1H6PB+y7/vJc1HSEZlZYuCghjN2TYTT5angdgRAcbviH7nnAVW YoSAjis8iWx6MaxtcIhljhwaqiwzNgIwfEYftjHJSj/ahD3rRwE35hzqzddgJ3ZTE1Jb kcGy4u1OU/bFQywE93OQ38MkaCWWRnJazsYk3bYE8+E+mrTr5krLFU0Z60vpEYHxG5Ml w7a4lgXwx2y/FALvggUbZOhnwAtwjtNSgrHOnZfv3LqSAPuxXsKCvXdJI2yBt4ZKATJk WcYTnY7LQrX0oMwevcaSwtG4rze59gFX/xa9qg8TMsWtDdE1gBtrBdIFhg05GjFBqvEt BYCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=bFtOB5wg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a12si11294938ion.18.2021.06.29.01.42.44; Tue, 29 Jun 2021 01:42:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=bFtOB5wg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232614AbhF2Imp (ORCPT + 99 others); Tue, 29 Jun 2021 04:42:45 -0400 Received: from mail.kernel.org ([198.145.29.99]:53468 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232572AbhF2Imn (ORCPT ); Tue, 29 Jun 2021 04:42:43 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 55FD961DC8; Tue, 29 Jun 2021 08:40:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1624956017; bh=3W16h0Qhvidbw6bBtrkPf3V2LDrQFbXK3ZE6M+o2jOA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bFtOB5wgziMB+XPuW1ialu+x8Esvk+SRs1GI7KTt+YmudpGimFmDTK+EKQIWik8th tslHjwCFUzchkpLWL0Jf5DgY4Yd5ae+BAK8i3OoM6+59W0e0YFth3sw8F3pe5NGcdP 4KpSaKfhWevBR3+rv8y71tn+CWuzt3FSRJ5g7iW+N4twIbjCSzu5q6ZABD0JRA+tif WFAO1lRKqhkWQvTvAR907aLsmQwIwObolaO8skATqtgeotDI7TrdsdqFBMXDh0l68A +S7YIsQBuk0+8f3smn2pl7WDq8IWw4oIWeY0V5rdHzD34RnjGu1K2lgN9kGx8X/yyG wJkKctdLoIsdg== From: Leon Romanovsky To: Doug Ledford , Jason Gunthorpe Cc: Maor Gottlieb , Dennis Dalessandro , linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, Mike Marciniszyn , Yishai Hadas , Zhu Yanjun Subject: [PATCH rdma-next v1 1/2] lib/scatterlist: Fix wrong update of orig_nents Date: Tue, 29 Jun 2021 11:40:01 +0300 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Maor Gottlieb orig_nents should represent the number of entries with pages, but __sg_alloc_table_from_pages sets orig_nents as the number of total entries in the table. This is wrong when the API is used for dynamic allocation where not all the table entries are mapped with pages. It wasn't observed until now, since RDMA umem who uses this API in the dynamic form doesn't use orig_nents implicit or explicit by the scatterlist APIs. Fix it by: 1. Set orig_nents as number of entries with pages also in __sg_alloc_table_from_pages. 2. Add a new field total_nents to reflect the total number of entries in the table. This is required for the release flow (sg_free_table). This filed should be used internally only by scatterlist. Fixes: 07da1223ec93 ("lib/scatterlist: Add support in dynamic allocation of SG table from pages") Signed-off-by: Maor Gottlieb Signed-off-by: Leon Romanovsky --- include/linux/scatterlist.h | 8 ++++++-- lib/scatterlist.c | 32 ++++++++------------------------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 6f70572b2938..1c889141eb91 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -35,8 +35,12 @@ struct scatterlist { struct sg_table { struct scatterlist *sgl; /* the list */ - unsigned int nents; /* number of mapped entries */ - unsigned int orig_nents; /* original size of list */ + unsigned int nents; /* number of DMA mapped entries */ + unsigned int orig_nents; /* number of CPU mapped entries */ + /* The fields below should be used internally only by + * scatterlist implementation. + */ + unsigned int total_nents; /* number of total entries in the table */ }; /* diff --git a/lib/scatterlist.c b/lib/scatterlist.c index a59778946404..6db70a1e7dd0 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -192,33 +192,26 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents) void __sg_free_table(struct sg_table *table, unsigned int max_ents, unsigned int nents_first_chunk, sg_free_fn *free_fn) { - struct scatterlist *sgl, *next; + struct scatterlist *sgl, *next = NULL; unsigned curr_max_ents = nents_first_chunk ?: max_ents; if (unlikely(!table->sgl)) return; sgl = table->sgl; - while (table->orig_nents) { - unsigned int alloc_size = table->orig_nents; - unsigned int sg_size; + while (table->total_nents) { + unsigned int alloc_size = table->total_nents; /* * If we have more than max_ents segments left, * then assign 'next' to the sg table after the current one. - * sg_size is then one less than alloc size, since the last - * element is the chain pointer. */ if (alloc_size > curr_max_ents) { next = sg_chain_ptr(&sgl[curr_max_ents - 1]); alloc_size = curr_max_ents; - sg_size = alloc_size - 1; - } else { - sg_size = alloc_size; - next = NULL; } - table->orig_nents -= sg_size; + table->total_nents -= alloc_size; if (nents_first_chunk) nents_first_chunk = 0; else @@ -301,20 +294,11 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, } else { sg = alloc_fn(alloc_size, gfp_mask); } - if (unlikely(!sg)) { - /* - * Adjust entry count to reflect that the last - * entry of the previous table won't be used for - * linkage. Without this, sg_kfree() may get - * confused. - */ - if (prv) - table->nents = ++table->orig_nents; - + if (unlikely(!sg)) return -ENOMEM; - } sg_init_table(sg, alloc_size); + table->total_nents += alloc_size; table->nents = table->orig_nents += sg_size; /* @@ -385,12 +369,11 @@ static struct scatterlist *get_next_sg(struct sg_table *table, if (!new_sg) return ERR_PTR(-ENOMEM); sg_init_table(new_sg, alloc_size); + table->total_nents += alloc_size; if (cur) { __sg_chain(next_sg, new_sg); - table->orig_nents += alloc_size - 1; } else { table->sgl = new_sg; - table->orig_nents = alloc_size; table->nents = 0; } return new_sg; @@ -515,6 +498,7 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt, cur_page = j; } sgt->nents += added_nents; + sgt->orig_nents = sgt->nents; out: if (!left_pages) sg_mark_end(s); -- 2.31.1