From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701479 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93602C433F5 for ; Thu, 30 Dec 2021 14:42:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239842AbhL3OmH (ORCPT ); Thu, 30 Dec 2021 09:42:07 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:49973 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235784AbhL3OmH (ORCPT ); Thu, 30 Dec 2021 09:42:07 -0500 X-Greylist: delayed 4311 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:07 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=S1MxFhNkRqNtF8cNgTKG1aWD8I0cArSeeYZ1LCi9IyY=; b=gQuBI J/yh7So1jopa2gZ0eb5jM4PAnSZdsumbkSiw0C5+DNMByHFQvvQyuL9Go9VvqnMH0/AV5nwS1TIHi JV15/d4vrBSeRtCOTRj+PKzsbCDPODqkweC7xtGNUcJNWMaLXeR4714v9FzHMvejhIo6400+sbkOL mUci50A2igtc3Jyh5RL1OhPZQFt6ZwIR8xiWwFIfA25spfBXJxI2mXgtk23+UnvmYsXPkJ1kiyMe3 ZGlp90tLmuOqDd4lcVsK8fZF4GkjYUP+YXGvlchS02FuNMKcPhHYy3oPlYk+Zq/vPFqaXaOafh+TM XLDaFl7eHRzxEU7iVZWnzdfULHW4w==; Message-Id: <783ba37c1566dd715b9a67d437efa3b77e3cd1a7.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 01/12] net/9p: show error message if user 'msize' cannot be satisfied To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org If user supplied a large value with the 'msize' option, then client would silently limit that 'msize' value to the maximum value supported by transport. That's a bit confusing for users of not having any indication why the preferred 'msize' value could not be satisfied. Reported-by: Vivek Goyal Signed-off-by: Christian Schoenebeck --- net/9p/client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/9p/client.c b/net/9p/client.c index d062f1e5bfb0..8bba0d9cf975 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1038,8 +1038,13 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) if (err) goto put_trans; - if (clnt->msize > clnt->trans_mod->maxsize) + if (clnt->msize > clnt->trans_mod->maxsize) { clnt->msize = clnt->trans_mod->maxsize; + pr_info("Limiting 'msize' to %d as this is the maximum " + "supported by transport %s\n", + clnt->msize, clnt->trans_mod->name + ); + } if (clnt->msize < 4096) { p9_debug(P9_DEBUG_ERROR, From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701459 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2CEFC433EF for ; Thu, 30 Dec 2021 14:13:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239866AbhL3ONU (ORCPT ); Thu, 30 Dec 2021 09:13:20 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:40227 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233197AbhL3ONT (ORCPT ); Thu, 30 Dec 2021 09:13:19 -0500 X-Greylist: delayed 2574 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:13:19 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=qmr6NzirhQbECLF80TyXWFZZKMifOhdiyj0CEd1zM38=; b=lwTCH Wy104oxksDimT5qHWw/YrgdqEhVfVu7fM/S1lyrZtXKTT2lRvkemdYYXrW/B/D12IVacm7zL3/0/T tLEXjoHgmsKSJDfXG4qHCqgj3ZWs5ngABPxiVg5+nVf0gJHKt63QLR5sRYR8iMK17mjRldGRnj3/j mSTxZVFBP21yLh06TtD+1E1iiJmFLkneBhK79Y+zHVDM/v+dxi6NaIa38KW3qXOihIprLuLapjbhp OU7kI83OqP+GGurNFTShz81jUUrts/21SJKVUCwwo06ioYxl7yziZYNs5irjH4/wpu+4HE6vazCTq RN7boObvA/ceRANi4chBVjWiteapQ==; Message-Id: In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 02/12] 9p/trans_virtio: separate allocation of scatter gather list To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The scatter gather list in struct virtio_chan currently resides as compile-time constant size array directly within the contiguous struct virtio_chan's memory space. Separate memory space and allocation of the scatter gather list from memory space and allocation of struct virtio_chan. Signed-off-by: Christian Schoenebeck --- net/9p/trans_virtio.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index bd5a89c4960d..7f0c992c0f68 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -77,7 +77,7 @@ struct virtio_chan { */ unsigned long p9_max_pages; /* Scatterlist: can be too big for stack. */ - struct scatterlist sg[VIRTQUEUE_NUM]; + struct scatterlist *sg; /** * @tag: name to identify a mount null terminated */ @@ -574,6 +574,14 @@ static int p9_virtio_probe(struct virtio_device *vdev) goto fail; } + chan->sg = kmalloc_array(VIRTQUEUE_NUM, + sizeof(struct scatterlist), GFP_KERNEL); + if (!chan->sg) { + pr_err("Failed to allocate virtio 9P channel\n"); + err = -ENOMEM; + goto out_free_chan_shallow; + } + chan->vdev = vdev; /* We expect one virtqueue, for requests. */ @@ -635,6 +643,8 @@ static int p9_virtio_probe(struct virtio_device *vdev) out_free_vq: vdev->config->del_vqs(vdev); out_free_chan: + kfree(chan->sg); +out_free_chan_shallow: kfree(chan); fail: return err; @@ -728,6 +738,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); kfree(chan->tag); kfree(chan->vc_wq); + kfree(chan->sg); kfree(chan); } From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701480 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9AF67C433FE for ; Thu, 30 Dec 2021 14:42:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239897AbhL3OmJ (ORCPT ); Thu, 30 Dec 2021 09:42:09 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:49973 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235784AbhL3OmI (ORCPT ); Thu, 30 Dec 2021 09:42:08 -0500 X-Greylist: delayed 4297 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:08 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=g86nOUNEYXZotGDC9WzvAD9cmWA0gMSDz40Z/V7NIeQ=; b=cyFmA ZSG8jfjWiJT4BgZ7NDCQ8iyahkY4liwY5jiM4zs6cWAi18Z2o8OsXf8cNvS9NAXGfi2YjJPXBNry9 ZDGitV0cF32+RDSy48mRW/+kMSVFm2YjYSAy2OTkxqnvk6NrWBaowWs2eZyr//o2BPS+q+NyTUPGY 044YZE9utscRJPI72YIiEbx+xdD6OMVHm61gZjrjpYvc2o6M8k1LjvqqDI7J++u5S2MFuS0oEuDKC hUs2ZoYrZnZmPIqMYgV5aLNp/exBYjSsd/v/S3e4AsN97iymBgtd/l7tCLN5KxKc9hnTaRk0POFgM NRozal/ZkiKrB7QXQTVWUtKCbVDXw==; Message-Id: <7ec67285cf793e0bfe5aee7ccd37580cf9addb17.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 03/12] 9p/trans_virtio: turn amount of sg lists into runtime info To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The size of scatter/gather lists used by the virtio transport is currently hard coded. Refactor this to using a runtime variable. Signed-off-by: Christian Schoenebeck --- net/9p/trans_virtio.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 7f0c992c0f68..d063c69b85b7 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -36,7 +36,7 @@ #include #include "trans_common.h" -#define VIRTQUEUE_NUM 128 +#define VIRTQUEUE_DEFAULT_NUM 128 /* a single mutex to manage channel initialization and attachment */ static DEFINE_MUTEX(virtio_9p_lock); @@ -54,6 +54,7 @@ static atomic_t vp_pinned = ATOMIC_INIT(0); * @vc_wq: wait queue for waiting for thing to be added to ring buf * @p9_max_pages: maximum number of pinned pages * @sg: scatter gather list which is used to pack a request (protected?) + * @sg_n: amount of elements in sg array * @chan_list: linked list of channels * * We keep all per-channel information in a structure. @@ -78,6 +79,7 @@ struct virtio_chan { unsigned long p9_max_pages; /* Scatterlist: can be too big for stack. */ struct scatterlist *sg; + size_t sg_n; /** * @tag: name to identify a mount null terminated */ @@ -270,12 +272,12 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) out_sgs = in_sgs = 0; /* Handle out VirtIO ring buffers */ out = pack_sg_list(chan->sg, 0, - VIRTQUEUE_NUM, req->tc.sdata, req->tc.size); + chan->sg_n, req->tc.sdata, req->tc.size); if (out) sgs[out_sgs++] = chan->sg; in = pack_sg_list(chan->sg, out, - VIRTQUEUE_NUM, req->rc.sdata, req->rc.capacity); + chan->sg_n, req->rc.sdata, req->rc.capacity); if (in) sgs[out_sgs + in_sgs++] = chan->sg + out; @@ -447,14 +449,14 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, /* out data */ out = pack_sg_list(chan->sg, 0, - VIRTQUEUE_NUM, req->tc.sdata, req->tc.size); + chan->sg_n, req->tc.sdata, req->tc.size); if (out) sgs[out_sgs++] = chan->sg; if (out_pages) { sgs[out_sgs++] = chan->sg + out; - out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, + out += pack_sg_list_p(chan->sg, out, chan->sg_n, out_pages, out_nr_pages, offs, outlen); } @@ -466,13 +468,13 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, * allocated memory and payload onto the user buffer. */ in = pack_sg_list(chan->sg, out, - VIRTQUEUE_NUM, req->rc.sdata, in_hdr_len); + chan->sg_n, req->rc.sdata, in_hdr_len); if (in) sgs[out_sgs + in_sgs++] = chan->sg + out; if (in_pages) { sgs[out_sgs + in_sgs++] = chan->sg + out + in; - in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, + in += pack_sg_list_p(chan->sg, out + in, chan->sg_n, in_pages, in_nr_pages, offs, inlen); } @@ -574,13 +576,14 @@ static int p9_virtio_probe(struct virtio_device *vdev) goto fail; } - chan->sg = kmalloc_array(VIRTQUEUE_NUM, + chan->sg = kmalloc_array(VIRTQUEUE_DEFAULT_NUM, sizeof(struct scatterlist), GFP_KERNEL); if (!chan->sg) { pr_err("Failed to allocate virtio 9P channel\n"); err = -ENOMEM; goto out_free_chan_shallow; } + chan->sg_n = VIRTQUEUE_DEFAULT_NUM; chan->vdev = vdev; @@ -593,7 +596,7 @@ static int p9_virtio_probe(struct virtio_device *vdev) chan->vq->vdev->priv = chan; spin_lock_init(&chan->lock); - sg_init_table(chan->sg, VIRTQUEUE_NUM); + sg_init_table(chan->sg, chan->sg_n); chan->inuse = false; if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { @@ -777,7 +780,7 @@ static struct p9_trans_module p9_virtio_trans = { * that are not at page boundary, that can result in an extra * page in zero copy. */ - .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3), + .maxsize = PAGE_SIZE * (VIRTQUEUE_DEFAULT_NUM - 3), .def = 1, .owner = THIS_MODULE, }; From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701455 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B13AC433F5 for ; Thu, 30 Dec 2021 14:12:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239849AbhL3OMk (ORCPT ); Thu, 30 Dec 2021 09:12:40 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:34649 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233197AbhL3OMk (ORCPT ); Thu, 30 Dec 2021 09:12:40 -0500 X-Greylist: delayed 2520 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:12:39 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=WP3n7tpB+D025yF74slHQQEWSBQcJ+0mlSqy58dljRg=; b=mj+An VdLfCm7I8hkOEG8OaVBcxxclOtqULbLWn2iSvVIeFLqAJzH+K4L6Vcii703ZyKiHJgOu7cDxRq9VS 5h4PIhoQq8+oiGBYIIhZnEpgQ9r4o5mUHIPXN8jSweWxz9eGuLB0CGeDnNdg5843g7LHn5wcD7/hf zEF2IunkwlavqyqpY0It3N83g2NBRjMoFBVolaiMa61Qw7g83J7tp3yPlcuDpqIE56Gh01Vf74QXh KUEJYBPL6F6FARJB5lJfzzwuGTmoVQCrHgomJSD1DeAle5yL4JTCxOUPvpQYA0OUD+S1ArNLPW/1V 1vEDOpeXWqoXGJOmvyxMVqNq5uiuw==; Message-Id: <103e92cc446c58d459c034973481d2f763a7006e.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 04/12] 9p/trans_virtio: introduce struct virtqueue_sg To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The amount of elements in a scatter/gather list is limited to approximately 128 elements. To allow going beyond that limit with subsequent patches, pave the way by turning the one- dimensional sg list array into a two-dimensional array, i.e: sg[128] becomes sgl[nsgl][SG_MAX_SINGLE_ALLOC] As the value of 'nsgl' is exactly (still) 1 in this commit and the compile-time (compiler and architecture dependent) value of 'SG_MAX_SINGLE_ALLOC' equals approximately the previous hard coded 128 elements, this commit is therefore more of a preparatory refactoring then actual behaviour change. A custom struct virtqueue_sg is defined instead of using shared API struct sg_table, because the latter would not allow to resize the table after allocation. sg_append_table API OTOH would not fit either, because it requires a list of pages beforehand upon allocation. And both APIs only support all-or-nothing allocation. Signed-off-by: Christian Schoenebeck --- net/9p/trans_virtio.c | 193 ++++++++++++++++++++++++++++++++---------- 1 file changed, 147 insertions(+), 46 deletions(-) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index d063c69b85b7..656562a66f06 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -36,7 +36,31 @@ #include #include "trans_common.h" -#define VIRTQUEUE_DEFAULT_NUM 128 +/** + * struct virtqueue_sg - (chained) scatter gather lists for virtqueue data + * transmission + * @nsgl: amount of elements (in first dimension) of array field @sgl + * @sgl: two-dimensional array, i.e. sgl[nsgl][SG_MAX_SINGLE_ALLOC] + */ +struct virtqueue_sg { + unsigned int nsgl; + struct scatterlist *sgl[]; +}; + +/* + * Default value for field nsgl in struct virtqueue_sg, which defines the + * initial virtio data transmission capacity when this virtio transport is + * probed. + */ +#define VIRTQUEUE_SG_NSGL_DEFAULT 1 + +/* maximum value for field nsgl in struct virtqueue_sg */ +#define VIRTQUEUE_SG_NSGL_MAX \ + ((PAGE_SIZE - sizeof(struct virtqueue_sg)) / \ + sizeof(struct scatterlist *)) \ + +/* last entry per sg list is used for chaining (pointer to next list) */ +#define SG_USER_PAGES_PER_LIST (SG_MAX_SINGLE_ALLOC - 1) /* a single mutex to manage channel initialization and attachment */ static DEFINE_MUTEX(virtio_9p_lock); @@ -53,8 +77,7 @@ static atomic_t vp_pinned = ATOMIC_INIT(0); * @ring_bufs_avail: flag to indicate there is some available in the ring buf * @vc_wq: wait queue for waiting for thing to be added to ring buf * @p9_max_pages: maximum number of pinned pages - * @sg: scatter gather list which is used to pack a request (protected?) - * @sg_n: amount of elements in sg array + * @vq_sg: table of scatter gather lists, which are used to pack a request * @chan_list: linked list of channels * * We keep all per-channel information in a structure. @@ -77,9 +100,7 @@ struct virtio_chan { * will be placing it in each channel. */ unsigned long p9_max_pages; - /* Scatterlist: can be too big for stack. */ - struct scatterlist *sg; - size_t sg_n; + struct virtqueue_sg *vq_sg; /** * @tag: name to identify a mount null terminated */ @@ -96,6 +117,92 @@ static unsigned int rest_of_page(void *data) return PAGE_SIZE - offset_in_page(data); } +/** + * vq_sg_page - returns user page for given page index + * @vq_sg: scatter gather lists used by this transport + * @page: user page index across all scatter gather lists + */ +static struct scatterlist *vq_sg_page(struct virtqueue_sg *vq_sg, size_t page) +{ + unsigned int node = page / SG_USER_PAGES_PER_LIST; + unsigned int leaf = page % SG_USER_PAGES_PER_LIST; + BUG_ON(node >= VIRTQUEUE_SG_NSGL_MAX); + return &vq_sg->sgl[node][leaf]; +} + +/** + * vq_sg_npages - returns total number of individual user pages in passed + * scatter gather lists + * @vq_sg: scatter gather lists to be counted + */ +static size_t vq_sg_npages(struct virtqueue_sg *vq_sg) +{ + return vq_sg->nsgl * SG_USER_PAGES_PER_LIST; +} + +/** + * vq_sg_free - free all memory previously allocated for @vq_sg + * @vq_sg: scatter gather lists to be freed + */ +static void vq_sg_free(struct virtqueue_sg *vq_sg) +{ + unsigned int i; + + if (!vq_sg) + return; + + for (i = 0; i < vq_sg->nsgl; ++i) { + kfree(vq_sg->sgl[i]); + } + kfree(vq_sg); +} + +/** + * vq_sg_alloc - allocates and returns @nsgl scatter gather lists + * @nsgl: amount of scatter gather lists to be allocated + * If @nsgl is larger than one then chained lists are used if supported by + * architecture. + */ +static struct virtqueue_sg *vq_sg_alloc(unsigned int nsgl) +{ + struct virtqueue_sg *vq_sg; + unsigned int i; + + BUG_ON(!nsgl || nsgl > VIRTQUEUE_SG_NSGL_MAX); +#ifdef CONFIG_ARCH_NO_SG_CHAIN + if (WARN_ON_ONCE(nsgl > 1)) + return NULL; +#endif + + vq_sg = kzalloc(sizeof(struct virtqueue_sg) + + nsgl * sizeof(struct scatterlist *), + GFP_KERNEL); + + if (!vq_sg) + return NULL; + + vq_sg->nsgl = nsgl; + + for (i = 0; i < nsgl; ++i) { + vq_sg->sgl[i] = kmalloc_array( + SG_MAX_SINGLE_ALLOC, sizeof(struct scatterlist), + GFP_KERNEL + ); + if (!vq_sg->sgl[i]) { + vq_sg_free(vq_sg); + return NULL; + } + sg_init_table(vq_sg->sgl[i], SG_MAX_SINGLE_ALLOC); + if (i) { + /* chain the lists */ + sg_chain(vq_sg->sgl[i - 1], SG_MAX_SINGLE_ALLOC, + vq_sg->sgl[i]); + } + } + sg_mark_end(&vq_sg->sgl[nsgl - 1][SG_MAX_SINGLE_ALLOC - 1]); + return vq_sg; +} + /** * p9_virtio_close - reclaim resources of a channel * @client: client instance @@ -158,9 +265,8 @@ static void req_done(struct virtqueue *vq) /** * pack_sg_list - pack a scatter gather list from a linear buffer - * @sg: scatter/gather list to pack into + * @vq_sg: scatter/gather lists to pack into * @start: which segment of the sg_list to start at - * @limit: maximum segment to pack data to * @data: data to pack into scatter/gather list * @count: amount of data to pack into the scatter/gather list * @@ -170,11 +276,12 @@ static void req_done(struct virtqueue *vq) * */ -static int pack_sg_list(struct scatterlist *sg, int start, - int limit, char *data, int count) +static int pack_sg_list(struct virtqueue_sg *vq_sg, int start, + char *data, int count) { int s; int index = start; + size_t limit = vq_sg_npages(vq_sg); while (count) { s = rest_of_page(data); @@ -182,13 +289,13 @@ static int pack_sg_list(struct scatterlist *sg, int start, s = count; BUG_ON(index >= limit); /* Make sure we don't terminate early. */ - sg_unmark_end(&sg[index]); - sg_set_buf(&sg[index++], data, s); + sg_unmark_end(vq_sg_page(vq_sg, index)); + sg_set_buf(vq_sg_page(vq_sg, index++), data, s); count -= s; data += s; } if (index-start) - sg_mark_end(&sg[index - 1]); + sg_mark_end(vq_sg_page(vq_sg, index - 1)); return index-start; } @@ -208,21 +315,21 @@ static int p9_virtio_cancelled(struct p9_client *client, struct p9_req_t *req) /** * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer, * this takes a list of pages. - * @sg: scatter/gather list to pack into + * @vq_sg: scatter/gather lists to pack into * @start: which segment of the sg_list to start at - * @limit: maximum number of pages in sg list. * @pdata: a list of pages to add into sg. * @nr_pages: number of pages to pack into the scatter/gather list * @offs: amount of data in the beginning of first page _not_ to pack * @count: amount of data to pack into the scatter/gather list */ static int -pack_sg_list_p(struct scatterlist *sg, int start, int limit, +pack_sg_list_p(struct virtqueue_sg *vq_sg, int start, struct page **pdata, int nr_pages, size_t offs, int count) { int i = 0, s; int data_off = offs; int index = start; + size_t limit = vq_sg_npages(vq_sg); BUG_ON(nr_pages > (limit - start)); /* @@ -235,15 +342,16 @@ pack_sg_list_p(struct scatterlist *sg, int start, int limit, s = count; BUG_ON(index >= limit); /* Make sure we don't terminate early. */ - sg_unmark_end(&sg[index]); - sg_set_page(&sg[index++], pdata[i++], s, data_off); + sg_unmark_end(vq_sg_page(vq_sg, index)); + sg_set_page(vq_sg_page(vq_sg, index++), pdata[i++], s, + data_off); data_off = 0; count -= s; nr_pages--; } if (index-start) - sg_mark_end(&sg[index - 1]); + sg_mark_end(vq_sg_page(vq_sg, index - 1)); return index - start; } @@ -271,15 +379,13 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) out_sgs = in_sgs = 0; /* Handle out VirtIO ring buffers */ - out = pack_sg_list(chan->sg, 0, - chan->sg_n, req->tc.sdata, req->tc.size); + out = pack_sg_list(chan->vq_sg, 0, req->tc.sdata, req->tc.size); if (out) - sgs[out_sgs++] = chan->sg; + sgs[out_sgs++] = vq_sg_page(chan->vq_sg, 0); - in = pack_sg_list(chan->sg, out, - chan->sg_n, req->rc.sdata, req->rc.capacity); + in = pack_sg_list(chan->vq_sg, out, req->rc.sdata, req->rc.capacity); if (in) - sgs[out_sgs + in_sgs++] = chan->sg + out; + sgs[out_sgs + in_sgs++] = vq_sg_page(chan->vq_sg, out); err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req, GFP_ATOMIC); @@ -448,16 +554,15 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, out_sgs = in_sgs = 0; /* out data */ - out = pack_sg_list(chan->sg, 0, - chan->sg_n, req->tc.sdata, req->tc.size); + out = pack_sg_list(chan->vq_sg, 0, req->tc.sdata, req->tc.size); if (out) - sgs[out_sgs++] = chan->sg; + sgs[out_sgs++] = vq_sg_page(chan->vq_sg, 0); if (out_pages) { - sgs[out_sgs++] = chan->sg + out; - out += pack_sg_list_p(chan->sg, out, chan->sg_n, - out_pages, out_nr_pages, offs, outlen); + sgs[out_sgs++] = vq_sg_page(chan->vq_sg, out); + out += pack_sg_list_p(chan->vq_sg, out, out_pages, + out_nr_pages, offs, outlen); } /* @@ -467,15 +572,14 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, * Arrange in such a way that server places header in the * allocated memory and payload onto the user buffer. */ - in = pack_sg_list(chan->sg, out, - chan->sg_n, req->rc.sdata, in_hdr_len); + in = pack_sg_list(chan->vq_sg, out, req->rc.sdata, in_hdr_len); if (in) - sgs[out_sgs + in_sgs++] = chan->sg + out; + sgs[out_sgs + in_sgs++] = vq_sg_page(chan->vq_sg, out); if (in_pages) { - sgs[out_sgs + in_sgs++] = chan->sg + out + in; - in += pack_sg_list_p(chan->sg, out + in, chan->sg_n, - in_pages, in_nr_pages, offs, inlen); + sgs[out_sgs + in_sgs++] = vq_sg_page(chan->vq_sg, out + in); + in += pack_sg_list_p(chan->vq_sg, out + in, in_pages, + in_nr_pages, offs, inlen); } BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs)); @@ -576,14 +680,12 @@ static int p9_virtio_probe(struct virtio_device *vdev) goto fail; } - chan->sg = kmalloc_array(VIRTQUEUE_DEFAULT_NUM, - sizeof(struct scatterlist), GFP_KERNEL); - if (!chan->sg) { + chan->vq_sg = vq_sg_alloc(VIRTQUEUE_SG_NSGL_DEFAULT); + if (!chan->vq_sg) { pr_err("Failed to allocate virtio 9P channel\n"); err = -ENOMEM; goto out_free_chan_shallow; } - chan->sg_n = VIRTQUEUE_DEFAULT_NUM; chan->vdev = vdev; @@ -596,8 +698,6 @@ static int p9_virtio_probe(struct virtio_device *vdev) chan->vq->vdev->priv = chan; spin_lock_init(&chan->lock); - sg_init_table(chan->sg, chan->sg_n); - chan->inuse = false; if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { virtio_cread(vdev, struct virtio_9p_config, tag_len, &tag_len); @@ -646,7 +746,7 @@ static int p9_virtio_probe(struct virtio_device *vdev) out_free_vq: vdev->config->del_vqs(vdev); out_free_chan: - kfree(chan->sg); + vq_sg_free(chan->vq_sg); out_free_chan_shallow: kfree(chan); fail: @@ -741,7 +841,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); kfree(chan->tag); kfree(chan->vc_wq); - kfree(chan->sg); + vq_sg_free(chan->vq_sg); kfree(chan); } @@ -780,7 +880,8 @@ static struct p9_trans_module p9_virtio_trans = { * that are not at page boundary, that can result in an extra * page in zero copy. */ - .maxsize = PAGE_SIZE * (VIRTQUEUE_DEFAULT_NUM - 3), + .maxsize = PAGE_SIZE * + ((VIRTQUEUE_SG_NSGL_DEFAULT * SG_USER_PAGES_PER_LIST) - 3), .def = 1, .owner = THIS_MODULE, }; From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701456 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75C18C433F5 for ; Thu, 30 Dec 2021 14:13:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239865AbhL3OM7 (ORCPT ); Thu, 30 Dec 2021 09:12:59 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:54907 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239876AbhL3OM4 (ORCPT ); Thu, 30 Dec 2021 09:12:56 -0500 X-Greylist: delayed 2530 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:12:56 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=HRgmsvyQc5R1HqZKiatrCeJDIA/6CkbTdpYiY2zKJhY=; b=hTnCe o1Whg/tS14T1EiCLIom1oN1Ymow2h360wlmsCPKFdW1o/E5jptO/jc3ghECy5x4oQTjfcjE9V3rNi 0XAFV6+W5SrHqQ6aJQYfrKplD83GIyH4bYiuyYW+tjOuslK4OJ9ydyS6dCF/51Rb0L7qFvSU6wEaN 3LAjPKYsozzUVWObI3ORKU1/0FC2rLvt25DSnFm7pifvUqvG6/L0hynnnQas04uFC3s9IMPYR67h0 Cki9svDG1l1vps8GsTZj27pUZdMuIFL8QeQebWepy/AH2b//jwyskrQghftOFaBxUc3FC/0zjZ8sY 40+ogM7lMXi3lpZWsGjpSmHcM3U5g==; Message-Id: In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 05/12] net/9p: add trans_maxsize to struct p9_client To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org This new field 'trans_maxsize' optionally allows transport to update it to reflect the actual maximum msize supported by allocated transport channel. Signed-off-by: Christian Schoenebeck --- include/net/9p/client.h | 2 ++ net/9p/client.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/net/9p/client.h b/include/net/9p/client.h index ec1d1706f43c..f5718057fca4 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -87,6 +87,7 @@ struct p9_req_t { * struct p9_client - per client instance state * @lock: protect @fids and @reqs * @msize: maximum data size negotiated by protocol + * @trans_maxsize: actual maximum msize supported by transport channel * @proto_version: 9P protocol version to use * @trans_mod: module API instantiated with this client * @status: connection state @@ -101,6 +102,7 @@ struct p9_req_t { struct p9_client { spinlock_t lock; unsigned int msize; + unsigned int trans_maxsize; unsigned char proto_version; struct p9_trans_module *trans_mod; enum p9_trans_status status; diff --git a/net/9p/client.c b/net/9p/client.c index 8bba0d9cf975..20054addd81b 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1031,6 +1031,14 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) goto free_client; } + /* + * transport will get a chance to increase trans_maxsize (if + * necessary) and it may update trans_maxsize in create() function + * below accordingly to reflect the actual maximum size supported by + * the allocated transport channel + */ + clnt->trans_maxsize = clnt->trans_mod->maxsize; + p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); @@ -1038,8 +1046,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) if (err) goto put_trans; - if (clnt->msize > clnt->trans_mod->maxsize) { - clnt->msize = clnt->trans_mod->maxsize; + if (clnt->msize > clnt->trans_maxsize) { + clnt->msize = clnt->trans_maxsize; pr_info("Limiting 'msize' to %d as this is the maximum " "supported by transport %s\n", clnt->msize, clnt->trans_mod->name From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701482 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FE72C433EF for ; Thu, 30 Dec 2021 14:42:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240291AbhL3OmK (ORCPT ); Thu, 30 Dec 2021 09:42:10 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:49973 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239911AbhL3OmK (ORCPT ); Thu, 30 Dec 2021 09:42:10 -0500 X-Greylist: delayed 1747 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:10 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=bdokaC3xBdXiPGVcGW4l+R/dzrRmqhrBfDvrmO2qQhE=; b=IQYKQ LRfXvc+RGAFpseYHoK9IeYTuFF2M02Cm6iu4dHZ4HrDXp42O1fyRmPNzP7XrWKmupHfrPpRlhVxf+ XKjurLAWcpAAVd1W7YxnRrAn8NmbBy2qBqBuugeyI5QiSjru+kTc/Uos+8rI/V8MlI07pLuWXIrvB YE4AyuK4u+cjDnz/f/XNyE4dnZAt3BZ+G3Dk8yfz1QjdNo4tGGXORZjezWNvGrjg7ey13sY+THO8Y +mpR+obQnLrNyreh+ed3raM1R3IVOIG5rK88Oz8AZo4xACRqDJd1NZDGh/RtJGpU1mQNz89F4zV4j IuHrZIp3q/2q9QvjyWyw7MPRQoKKw==; Message-Id: <92bbeadaf5c6a0615b970bd01d6f51c455d6d988.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 06/12] 9p/trans_virtio: support larger msize values To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The virtio transport supports by default a 9p 'msize' of up to approximately 500 kB. This patch adds support for larger 'msize' values by resizing the amount of scatter/gather lists if required. Signed-off-by: Christian Schoenebeck --- net/9p/trans_virtio.c | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 656562a66f06..a02050c9742a 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -203,6 +203,31 @@ static struct virtqueue_sg *vq_sg_alloc(unsigned int nsgl) return vq_sg; } +/** + * vq_sg_resize - resize passed virtqueue scatter/gather lists to the passed + * amount of lists + * @_vq_sg: scatter/gather lists to be resized + * @nsgl: new amount of scatter/gather lists + */ +static int vq_sg_resize(struct virtqueue_sg **_vq_sg, unsigned int nsgl) +{ + struct virtqueue_sg *vq_sg; + + BUG_ON(!_vq_sg || !nsgl); + vq_sg = *_vq_sg; + if (vq_sg->nsgl == nsgl) + return 0; + + /* lazy resize implementation for now */ + vq_sg = vq_sg_alloc(nsgl); + if (!vq_sg) + return -ENOMEM; + + kfree(*_vq_sg); + *_vq_sg = vq_sg; + return 0; +} + /** * p9_virtio_close - reclaim resources of a channel * @client: client instance @@ -774,6 +799,10 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) struct virtio_chan *chan; int ret = -ENOENT; int found = 0; +#if !defined(CONFIG_ARCH_NO_SG_CHAIN) + size_t npages; + size_t nsgl; +#endif if (devname == NULL) return -EINVAL; @@ -796,6 +825,38 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) return ret; } + /* + * if user supplied an 'msize' option that's larger than what this + * transport supports by default, then try to allocate more sg lists + */ + if (client->msize > client->trans_maxsize) { +#ifdef CONFIG_ARCH_NO_SG_CHAIN + pr_info("limiting 'msize' to %d because architecture does not " + "support chained scatter gather lists\n", + client->trans_maxsize); +#else + npages = DIV_ROUND_UP(client->msize, PAGE_SIZE); + if (npages > chan->p9_max_pages) { + npages = chan->p9_max_pages; + pr_info("limiting 'msize' as it would exceed the max. " + "of %lu pages allowed on this system\n", + chan->p9_max_pages); + } + nsgl = DIV_ROUND_UP(npages, SG_USER_PAGES_PER_LIST); + if (nsgl > chan->vq_sg->nsgl) { + /* + * if resize fails, no big deal, then just + * continue with default msize instead + */ + if (!vq_sg_resize(&chan->vq_sg, nsgl)) { + client->trans_maxsize = + PAGE_SIZE * + ((nsgl * SG_USER_PAGES_PER_LIST) - 3); + } + } +#endif /* CONFIG_ARCH_NO_SG_CHAIN */ + } + client->trans = (void *)chan; client->status = Connected; chan->client = client; From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701481 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 781BAC433F5 for ; Thu, 30 Dec 2021 14:42:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240047AbhL3OmJ (ORCPT ); Thu, 30 Dec 2021 09:42:09 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:49973 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239861AbhL3OmJ (ORCPT ); Thu, 30 Dec 2021 09:42:09 -0500 X-Greylist: delayed 1785 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:09 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=WFwvsfcLSvXImvKzK0ROel4mXqUzpd6lHVm/jLVuHDE=; b=Ee7g7 G5HnqQhJEGfMv81jpIi6G1UhfTVbCfBVtiukJitpqyfq8ZruhC6YCbwQ7ZwpExnWgsHbx8qc/i0y3 T88FRIn3KMppGu/24A4Fl5PSZ0710wl7zR9KqA3TnnNMIw0Ap77JIgvJJT5sLAXFAifZqZJcFVY6r i2oTBQSZKKQdgiPrsYN8JuTMwtJ+YjkA84q+VbdUrTIh0+cjzUkwbpZCeUSeu6Uryekmb/8BpLGBv ZX7fMve5ywcVDl5NTqmgpG5jSI0OgypKZRZ6xwCK1a5tH8hfeJBXQgvhyokXLM82lxmaKs7bE6AyP BgIedodHR7RQXAQPPvA+Ab3XaIVLQ==; Message-Id: <35f29eb71a713fd6e595d8ea4d4f5131df5e33b8.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 07/12] 9p/trans_virtio: resize sg lists to whatever is possible To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Right now vq_sg_resize() used a lazy implementation following the all-or-nothing princible. So it either resized exactly to the requested new amount of sg lists, or it did not resize at all. The problem with this is if a user supplies a very large msize value, resize would simply fail and the user would stick to the default maximum msize supported by the virtio transport. To resolve this potential issue, change vq_sg_resize() to resize the passed sg list to whatever is possible on the machine. Signed-off-by: Christian Schoenebeck --- net/9p/trans_virtio.c | 68 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index a02050c9742a..580efa95eabd 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -208,24 +208,67 @@ static struct virtqueue_sg *vq_sg_alloc(unsigned int nsgl) * amount of lists * @_vq_sg: scatter/gather lists to be resized * @nsgl: new amount of scatter/gather lists + * + * Old scatter/gather lists are retained. Only growing the size is supported. + * If the requested amount cannot be satisfied, then lists are increased to + * whatever is possible. */ static int vq_sg_resize(struct virtqueue_sg **_vq_sg, unsigned int nsgl) { struct virtqueue_sg *vq_sg; + unsigned int i; + size_t sz; + int ret = 0; BUG_ON(!_vq_sg || !nsgl); vq_sg = *_vq_sg; + if (nsgl > VIRTQUEUE_SG_NSGL_MAX) + nsgl = VIRTQUEUE_SG_NSGL_MAX; if (vq_sg->nsgl == nsgl) return 0; + if (vq_sg->nsgl > nsgl) + return -ENOTSUPP; + + vq_sg = kzalloc(sizeof(struct virtqueue_sg) + + nsgl * sizeof(struct scatterlist *), + GFP_KERNEL); - /* lazy resize implementation for now */ - vq_sg = vq_sg_alloc(nsgl); if (!vq_sg) return -ENOMEM; + /* copy over old scatter gather lists */ + sz = sizeof(struct virtqueue_sg) + + (*_vq_sg)->nsgl * sizeof(struct scatterlist *); + memcpy(vq_sg, *_vq_sg, sz); + + vq_sg->nsgl = nsgl; + + for (i = (*_vq_sg)->nsgl; i < nsgl; ++i) { + vq_sg->sgl[i] = kmalloc_array( + SG_MAX_SINGLE_ALLOC, sizeof(struct scatterlist), + GFP_KERNEL + ); + /* + * handle failed allocation as soft error, we take whatever + * we get + */ + if (!vq_sg->sgl[i]) { + ret = -ENOMEM; + vq_sg->nsgl = nsgl = i; + break; + } + sg_init_table(vq_sg->sgl[i], SG_MAX_SINGLE_ALLOC); + if (i) { + /* chain the lists */ + sg_chain(vq_sg->sgl[i - 1], SG_MAX_SINGLE_ALLOC, + vq_sg->sgl[i]); + } + } + sg_mark_end(&vq_sg->sgl[nsgl - 1][SG_MAX_SINGLE_ALLOC - 1]); + kfree(*_vq_sg); *_vq_sg = vq_sg; - return 0; + return ret; } /** @@ -846,12 +889,21 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) if (nsgl > chan->vq_sg->nsgl) { /* * if resize fails, no big deal, then just - * continue with default msize instead + * continue with whatever we got + */ + vq_sg_resize(&chan->vq_sg, nsgl); + /* + * actual allocation size might be less than + * requested, so use vq_sg->nsgl instead of nsgl */ - if (!vq_sg_resize(&chan->vq_sg, nsgl)) { - client->trans_maxsize = - PAGE_SIZE * - ((nsgl * SG_USER_PAGES_PER_LIST) - 3); + client->trans_maxsize = + PAGE_SIZE * ((chan->vq_sg->nsgl * + SG_USER_PAGES_PER_LIST) - 3); + if (nsgl > chan->vq_sg->nsgl) { + pr_info("limiting 'msize' to %d as only %d " + "of %zu SG lists could be allocated", + client->trans_maxsize, + chan->vq_sg->nsgl, nsgl); } } #endif /* CONFIG_ARCH_NO_SG_CHAIN */ From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701484 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E96FC433EF for ; Thu, 30 Dec 2021 14:42:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240360AbhL3OmT (ORCPT ); Thu, 30 Dec 2021 09:42:19 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:32911 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240346AbhL3OmT (ORCPT ); Thu, 30 Dec 2021 09:42:19 -0500 X-Greylist: delayed 1796 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:19 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=wsH0zZJH3P8YpigJb796yoZLuqDz5KinnqHSkWbAOGs=; b=TQcZk M9zTyYEputBDZYa14c6KLLvLrmzfQEQjT3SVAGXBLhpgLwQeGmAOs6qeVDzZzB2lY/vOrNP6rgJsf OqivDL2zUCFjP/sKfIL3QmeWiWMQ2riOhU9j1xgWUgDRAiSNpB8o8WDVjbUYO7dmoZn6ooZkKcL77 vGFkAK35SXZ7LeZMtEQ2LfaQx5soU2RmQHFbZJRC4kvePl+fJP12oVPYDRcN4y27oEd0g40IPWZh0 V8xCEiYnHB7i84eDZD0t4Yrhk+T7sAsDKX94AM9sWmYAZ20j2XRuNTZbOpnqpy/jUwSQIxXEb569R LAtgGRe2/n35pmzXAHNcof1jKlKyA==; Message-Id: <39f81db5e5b25a1e4f94ad3b05552044209aff21.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 08/12] net/9p: limit 'msize' to KMALLOC_MAX_SIZE for all transports To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org This 9p client implementation is yet using linear message buffers for most message types, i.e. they use kmalloc() et al. for allocating continuous physical memory pages, which is usually limited to 4MB buffers. Use KMALLOC_MAX_SIZE though instead of a hard coded 4MB for constraining this more safely. Unfortunately we cannot simply replace the existing kmalloc() calls by vmalloc() ones, because that would yield in non-logical kernel addresses (for any vmalloc(>4MB) that is) which are in general not accessible by hosts like QEMU. In future we would replace those linear buffers by scatter/gather lists to eventually get rid of this limit (struct p9_fcall's sdata member by p9_fcall_init() and struct p9_fid's rdir member by v9fs_alloc_rdir_buf()). Signed-off-by: Christian Schoenebeck --- net/9p/client.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/9p/client.c b/net/9p/client.c index 20054addd81b..fab939541c81 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1042,6 +1042,17 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); + /* + * due to linear message buffers being used by client ATM + */ + if (clnt->msize > KMALLOC_MAX_SIZE) { + clnt->msize = KMALLOC_MAX_SIZE; + pr_info("Limiting 'msize' to %zu as this is the maximum " + "supported by this client version.\n", + (size_t) KMALLOC_MAX_SIZE + ); + } + err = clnt->trans_mod->create(clnt, dev_name, options); if (err) goto put_trans; From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701485 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B03FBC433EF for ; Thu, 30 Dec 2021 14:42:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240370AbhL3OmX (ORCPT ); Thu, 30 Dec 2021 09:42:23 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:56681 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240346AbhL3OmW (ORCPT ); Thu, 30 Dec 2021 09:42:22 -0500 X-Greylist: delayed 1811 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:21 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=JMpUBU0faqNlIU1d4S3Q7wytCNCfKZ32SXUnAyXuU0s=; b=Phykm t05EaqbB/CZ5TwdHKPcGyn+dANi8bGKZM9GIcJagQTdZouiyTlIwtIC5wXDf+Xty/rcoeB2TX452U IsKkwYw4yN02brunzuY5oXdGaPP/HrCXgZMS7psSOI5+Zc45cu+U2/FOafE19bQcZYmR54dzKMBhy 5V0b2Fl2N5DVFILqUDHSN0f/Xm1tu2iWLm9DGISXoCaKPcVJ/xvOBADhoyw0D7VPliMAtpxCzdrGQ i5WxT/VbSn7CrS4fHkxmsKy20wZkLZTRh2KZL7NclCOhBUPqhpML9gKtqkv6nNJBPz6crEw4UsZx1 a0ifNS2aunqCnf0y/d33yCrQgoe3Q==; Message-Id: <4b96331e3d113aeab2cfbe6e8f39da934eda418a.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 09/12] net/9p: split message size argument into 't_size' and 'r_size' pair To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Refactor 'max_size' argument of p9_tag_alloc() and 'req_size' argument of p9_client_prepare_req() both into a pair of arguments 't_size' and 'r_size' respectively to allow handling the buffer size for request and reply separately from each other. Signed-off-by: Christian Schoenebeck --- net/9p/client.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index fab939541c81..56be1658870d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -255,24 +255,26 @@ static struct kmem_cache *p9_req_cache; * p9_tag_alloc - Allocate a new request. * @c: Client session. * @type: Transaction type. - * @max_size: Maximum packet size for this request. + * @t_size: Buffer size for holding this request. + * @r_size: Buffer size for holding server's reply on this request. * * Context: Process context. * Return: Pointer to new request. */ static struct p9_req_t * -p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size) +p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size) { struct p9_req_t *req = kmem_cache_alloc(p9_req_cache, GFP_NOFS); - int alloc_msize = min(c->msize, max_size); + int alloc_tsize = min(c->msize, t_size); + int alloc_rsize = min(c->msize, r_size); int tag; if (!req) return ERR_PTR(-ENOMEM); - if (p9_fcall_init(c, &req->tc, alloc_msize)) + if (p9_fcall_init(c, &req->tc, alloc_tsize)) goto free_req; - if (p9_fcall_init(c, &req->rc, alloc_msize)) + if (p9_fcall_init(c, &req->rc, alloc_rsize)) goto free; p9pdu_reset(&req->tc); @@ -678,7 +680,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) } static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, - int8_t type, int req_size, + int8_t type, uint t_size, uint r_size, const char *fmt, va_list ap) { int err; @@ -694,7 +696,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, if (c->status == BeginDisconnect && type != P9_TCLUNK) return ERR_PTR(-EIO); - req = p9_tag_alloc(c, type, req_size); + req = p9_tag_alloc(c, type, t_size, r_size); if (IS_ERR(req)) return req; @@ -731,7 +733,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) struct p9_req_t *req; va_start(ap, fmt); - req = p9_client_prepare_req(c, type, c->msize, fmt, ap); + req = p9_client_prepare_req(c, type, c->msize, c->msize, fmt, ap); va_end(ap); if (IS_ERR(req)) return req; @@ -829,7 +831,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, /* We allocate a inline protocol data of only 4k bytes. * The actual content is passed in zero-copy fashion. */ - req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap); + req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, P9_ZC_HDR_SZ, fmt, ap); va_end(ap); if (IS_ERR(req)) return req; From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701486 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 29C6BC433EF for ; Thu, 30 Dec 2021 14:42:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240213AbhL3Om0 (ORCPT ); Thu, 30 Dec 2021 09:42:26 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:59481 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240346AbhL3Om0 (ORCPT ); Thu, 30 Dec 2021 09:42:26 -0500 X-Greylist: delayed 1810 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:25 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=7rxL+vVkRtDypNlhYjU20nqnGaFCHwV4VaWOzz8KKMM=; b=NQfff V9vMFphX1kMzXuSR3poklB7Vz+H+CSH0BlqZJOc0Ud+axB9zRLMJK5i42CHu1mkAxXmS6m/3Y2KUY kvS7fdqzzwH+ItfsyVsfDs14ul/GetOZ1LkMJ/qSuIa0CPh+TXur/y3QRVF3IIgkAYQpAo5TUeia+ 2k7m4SNn+Ydx6XR7tazOvIiqiFqhYwXc6Yzex1aw5VEOHVmZRoz74EqNBKiyvN37jMHN0vFL0Dzxe WLHluCS5vRZmPs3vvIiCpKnTXXabljPizwA9gigb9ndQ+wUwQBlEIG+vXnkt2+Q3SEf2PsGEL/yr5 BblsVky48VejvDHi0BOSqum3zQxPQ==; Message-Id: <7cb10547a122c32fdafd68c77f0625f9a4d9a8bf.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 10/12] 9p: add P9_ERRMAX for 9p2000 and 9p2000.u To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Add P9_ERRMAX macro to 9P protocol header which reflects the maximum error string length of Rerror replies for 9p2000 and 9p2000.u protocol versions. Unfortunately a maximum error string length is not defined by the 9p2000 spec, picking 128 as value for now, as this seems to be a common max. size for POSIX error strings in practice. 9p2000.L protocol version uses Rlerror replies instead which does not contain an error string. Signed-off-by: Christian Schoenebeck --- include/net/9p/9p.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 9c6ec78e47a5..a447acc55b02 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -331,6 +331,9 @@ enum p9_qid_t { /* size of header for zero copy read/write */ #define P9_ZC_HDR_SZ 4096 +/* maximum length of an error string */ +#define P9_ERRMAX 128 + /** * struct p9_qid - file system entity information * @type: 8-bit type &p9_qid_t From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701483 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80D91C433EF for ; Thu, 30 Dec 2021 14:42:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239861AbhL3OmQ (ORCPT ); Thu, 30 Dec 2021 09:42:16 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:39101 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240370AbhL3OmQ (ORCPT ); Thu, 30 Dec 2021 09:42:16 -0500 X-Greylist: delayed 1800 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:42:15 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=evr+Tviy1M3/uGNzt9x08PaZ+uzk9AbYvF3GmjxPwr4=; b=YYpul TIuY3Ae44CNKFXtylHgQiORXydPcCVIJSsX6Q78LOJ/cuqoXiJjl7IuVjxZ6sWz9v+JHlNF6xa3ta U9yK/FDl+pZXHPo2hGVyWNLdBvbh6hg7He1uVNj5/XIXW3fODUyY3HTKCTS7scrwPOF4Jm8aXkt9q oV2hcsBXZepRi76REA3RoBLnJwyxUdTPVH/2qcl7LcScCTXLPEpL3M0WckQ+emDDnTSwVEu2M5DdI HUcj6fBIitVb8eNbO931xu2Gp0Y+QqfdgKJ/5eyI8/76pB7V40YuPWMomVqH3/wy5Ip+K7rdpC9z/ 585UvSvxmSTv0L2QMD2AZzqxcyQsQ==; Message-Id: <3d9eab8f55c8e4f036cbbf38bbdddb1c867432e7.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 11/12] net/9p: add p9_msg_buf_size() To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org This new function calculates a buffer size suitable for holding the intended 9p request or response. For rather small message types (which applies to almost all 9p message types actually) simply use hard coded values. For some variable-length and potentially large message types calculate a more precise value according to what data is actually transmitted to avoid unnecessarily huge buffers. Signed-off-by: Christian Schoenebeck --- net/9p/protocol.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ net/9p/protocol.h | 2 + 2 files changed, 156 insertions(+) diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 3754c33e2974..49939e8cde2a 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c @@ -23,6 +23,160 @@ #include +/* len[2] text[len] */ +#define P9_STRLEN(s) \ + (2 + min_t(size_t, s ? strlen(s) : 0, USHRT_MAX)) + +/** + * p9_msg_buf_size - Returns a buffer size sufficiently large to hold the + * intended 9p message. + * @c: client + * @type: message type + * @fmt: format template for assembling request message + * (see p9pdu_vwritef) + * @ap: variable arguments to be fed to passed format template + * (see p9pdu_vwritef) + * + * Note: Even for response types (P9_R*) the format template and variable + * arguments must always be for the originating request type (P9_T*). + */ +size_t p9_msg_buf_size(struct p9_client *c, enum p9_msg_t type, + const char *fmt, va_list ap) +{ + /* size[4] type[1] tag[2] */ + const int hdr = 4 + 1 + 2; + /* ename[s] errno[4] */ + const int rerror_size = hdr + P9_ERRMAX + 4; + /* ecode[4] */ + const int rlerror_size = hdr + 4; + const int err_size = + c->proto_version == p9_proto_2000L ? rlerror_size : rerror_size; + + switch (type) { + + /* message types not used at all */ + case P9_TERROR: + case P9_TLERROR: + case P9_TAUTH: + case P9_RAUTH: + BUG(); + + /* variable length & potentially large message types */ + case P9_TATTACH: + BUG_ON(strcmp("ddss?u", fmt)); + va_arg(ap, int32_t); + va_arg(ap, int32_t); + { + const char *uname = va_arg(ap, const char *); + const char *aname = va_arg(ap, const char *); + /* fid[4] afid[4] uname[s] aname[s] n_uname[4] */ + return hdr + 4 + 4 + P9_STRLEN(uname) + P9_STRLEN(aname) + 4; + } + case P9_TWALK: + BUG_ON(strcmp("ddT", fmt)); + va_arg(ap, int32_t); + va_arg(ap, int32_t); + { + uint i, nwname = max(va_arg(ap, int), 0); + size_t wname_all; + const char **wnames = va_arg(ap, const char **); + for (i = 0, wname_all = 0; i < nwname; ++i) { + wname_all += P9_STRLEN(wnames[i]); + } + /* fid[4] newfid[4] nwname[2] nwname*(wname[s]) */ + return hdr + 4 + 4 + 2 + wname_all; + } + case P9_RWALK: + BUG_ON(strcmp("ddT", fmt)); + va_arg(ap, int32_t); + va_arg(ap, int32_t); + { + uint nwname = va_arg(ap, int); + /* nwqid[2] nwqid*(wqid[13]) */ + return max_t(size_t, hdr + 2 + nwname * 13, err_size); + } + case P9_TCREATE: + BUG_ON(strcmp("dsdb?s", fmt)); + va_arg(ap, int32_t); + { + const char *name = va_arg(ap, const char *); + if ((c->proto_version != p9_proto_2000u) && + (c->proto_version != p9_proto_2000L)) + /* fid[4] name[s] perm[4] mode[1] */ + return hdr + 4 + P9_STRLEN(name) + 4 + 1; + { + va_arg(ap, int32_t); + va_arg(ap, int); + { + const char *ext = va_arg(ap, const char *); + /* fid[4] name[s] perm[4] mode[1] extension[s] */ + return hdr + 4 + P9_STRLEN(name) + 4 + 1 + P9_STRLEN(ext); + } + } + } + case P9_TLCREATE: + BUG_ON(strcmp("dsddg", fmt)); + va_arg(ap, int32_t); + { + const char *name = va_arg(ap, const char *); + /* fid[4] name[s] flags[4] mode[4] gid[4] */ + return hdr + 4 + P9_STRLEN(name) + 4 + 4 + 4; + } + case P9_RREAD: + case P9_RREADDIR: + BUG_ON(strcmp("dqd", fmt)); + va_arg(ap, int32_t); + va_arg(ap, int64_t); + { + const int32_t count = va_arg(ap, int32_t); + /* count[4] data[count] */ + return max_t(size_t, hdr + 4 + count, err_size); + } + case P9_TWRITE: + BUG_ON(strcmp("dqV", fmt)); + va_arg(ap, int32_t); + va_arg(ap, int64_t); + { + const int32_t count = va_arg(ap, int32_t); + /* fid[4] offset[8] count[4] data[count] */ + return hdr + 4 + 8 + 4 + count; + } + case P9_TRENAMEAT: + BUG_ON(strcmp("dsds", fmt)); + va_arg(ap, int32_t); + { + const char *oldname = va_arg(ap, const char *); + va_arg(ap, int32_t); + { + const char *newname = va_arg(ap, const char *); + /* olddirfid[4] oldname[s] newdirfid[4] newname[s] */ + return hdr + 4 + P9_STRLEN(oldname) + 4 + P9_STRLEN(newname); + } + } + case P9_RERROR: + return rerror_size; + case P9_RLERROR: + return rlerror_size; + + /* small message types */ + case P9_TSTAT: + case P9_RSTAT: + case P9_TSYMLINK: + case P9_RREADLINK: + case P9_TXATTRWALK: + case P9_TXATTRCREATE: + case P9_TLINK: + case P9_TMKDIR: + case P9_TUNLINKAT: + return 8 * 1024; + + /* tiny message types */ + default: + return 4 * 1024; + + } +} + static int p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); diff --git a/net/9p/protocol.h b/net/9p/protocol.h index 6d719c30331a..ad2283d1f96b 100644 --- a/net/9p/protocol.h +++ b/net/9p/protocol.h @@ -8,6 +8,8 @@ * Copyright (C) 2008 by IBM, Corp. */ +size_t p9_msg_buf_size(struct p9_client *c, enum p9_msg_t type, + const char *fmt, va_list ap); int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, va_list ap); int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); From patchwork Thu Dec 30 13:23:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 12701453 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E5FDC433F5 for ; Thu, 30 Dec 2021 14:12:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239809AbhL3OMO (ORCPT ); Thu, 30 Dec 2021 09:12:14 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:37057 "EHLO lizzy.crudebyte.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239798AbhL3OMN (ORCPT ); Thu, 30 Dec 2021 09:12:13 -0500 X-Greylist: delayed 2521 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Dec 2021 09:12:13 EST DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=uZFzuHVsW9bTvGYFZ5r4LS0YJPrnwxn1A5YEmCqKBXY=; b=BrRO1 HJTeJ6iQrZzlzkcE4NYROqhLo9tAP30o3VGlvhOOqLApJs/b4gdHwh8cKNrdUBAb/N4/W1PSlx8ZN z2HZ+05Bg4GaeTnOBKgKLXJUprO1FikVXHA23JkAIFtpkWMnUrCHXYnaw13yALG6UckZGbZFycP2F xYhX2vDByNjtT+GJV/2Cgf6N0gjklYzDgUUX2DZtt8pfpxD3fqFT9U8v73M7qrQd6MMkmjozeqSh+ Q3/vkcgJeFXVo6MLg5WtBRTQAp/QrNwYwcZWA/EMMqC5uvDbfOEClVhdzbwuRHxOVHAUzqDg1ZHsb ot/8DoxOxj/X1FK0gcjM5PELiKczg==; Message-Id: <8c305df4646b65218978fc6474aa0f5f29b216a0.1640870037.git.linux_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Thu, 30 Dec 2021 14:23:18 +0100 Subject: [PATCH v4 12/12] net/9p: allocate appropriate reduced message buffers To: v9fs-developer@lists.sourceforge.net Cc: netdev@vger.kernel.org, Dominique Martinet , Eric Van Hensbergen , Latchesar Ionkov , Greg Kurz , Vivek Goyal , Nikolay Kichukov Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org So far 'msize' was simply used for all 9p message types, which is far too much and slowed down performance tremendously with large values for user configurable 'msize' option. Let's stop this waste by using the new p9_msg_buf_size() function for allocating more appropriate, smaller buffers according to what is actually sent over the wire. Signed-off-by: Christian Schoenebeck --- net/9p/client.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 56be1658870d..773915c95219 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -255,19 +255,35 @@ static struct kmem_cache *p9_req_cache; * p9_tag_alloc - Allocate a new request. * @c: Client session. * @type: Transaction type. - * @t_size: Buffer size for holding this request. - * @r_size: Buffer size for holding server's reply on this request. + * @t_size: Buffer size for holding this request + * (automatic calculation by format template if 0). + * @r_size: Buffer size for holding server's reply on this request + * (automatic calculation by format template if 0). + * @fmt: Format template for assembling 9p request message + * (see p9pdu_vwritef). + * @ap: Variable arguments to be fed to passed format template + * (see p9pdu_vwritef). * * Context: Process context. * Return: Pointer to new request. */ static struct p9_req_t * -p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size) +p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size, + const char *fmt, va_list ap) { struct p9_req_t *req = kmem_cache_alloc(p9_req_cache, GFP_NOFS); - int alloc_tsize = min(c->msize, t_size); - int alloc_rsize = min(c->msize, r_size); + int alloc_tsize; + int alloc_rsize; int tag; + va_list apc; + + va_copy(apc, ap); + alloc_tsize = min_t(size_t, c->msize, + t_size ?: p9_msg_buf_size(c, type, fmt, apc)); + va_end(apc); + + alloc_rsize = min_t(size_t, c->msize, + r_size ?: p9_msg_buf_size(c, type + 1, fmt, ap)); if (!req) return ERR_PTR(-ENOMEM); @@ -685,6 +701,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, { int err; struct p9_req_t *req; + va_list apc; p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type); @@ -696,7 +713,9 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, if (c->status == BeginDisconnect && type != P9_TCLUNK) return ERR_PTR(-EIO); - req = p9_tag_alloc(c, type, t_size, r_size); + va_copy(apc, ap); + req = p9_tag_alloc(c, type, t_size, r_size, fmt, apc); + va_end(apc); if (IS_ERR(req)) return req; @@ -733,7 +752,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) struct p9_req_t *req; va_start(ap, fmt); - req = p9_client_prepare_req(c, type, c->msize, c->msize, fmt, ap); + req = p9_client_prepare_req(c, type, 0, 0, fmt, ap); va_end(ap); if (IS_ERR(req)) return req;