From nobody Fri Sep 12 08:55:15 2025 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 81422C61DA4 for ; Sat, 11 Feb 2023 07:51:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229728AbjBKHvA (ORCPT ); Sat, 11 Feb 2023 02:51:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229637AbjBKHuz (ORCPT ); Sat, 11 Feb 2023 02:50:55 -0500 Received: from nautica.notk.org (ipv6.notk.org [IPv6:2001:41d0:1:7a93::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 28DFE5C487 for ; Fri, 10 Feb 2023 23:50:54 -0800 (PST) Received: by nautica.notk.org (Postfix, from userid 108) id 7DE77C022; Sat, 11 Feb 2023 08:51:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101875; bh=UfsDrit7eLpVkZZfZcRzk8BZOU6gKynjWaH0yapJsnY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Qx0iUfzqF/T5Yf4GrgHdYITABitWEhGjzLEbJRqCdfw7m6bG2rzy3p3LI7y3tZjFB dBgR7K0l8tXkQi/TWBim0tBCufYAd5d9xjUbbjbr/ZGhTGMMi8AIlNyu4VYZqA6UWt wuA2NA4A3e/nLp6YFoC1O3hFa+BqvIYh5+8ry+594hRzqv7zF1rpzVF9ts6outy8fO uF3jTEkvu9gAgYAQ+Di0tyd+Ic3I8RzypErVtfyrhKn+ViFSwXJEO2Dra/WAYynLdW Yq4AMS1JX2upKu7Kznfi7E7L9PW8i0IgX2OGQdkI6VnjRHh63b7z1RTG/FUx+aYRUi 9G9o6vkzi6Asw== Received: from odin.codewreck.org (localhost [127.0.0.1]) by nautica.notk.org (Postfix) with ESMTPS id E1A88C01C; Sat, 11 Feb 2023 08:51:09 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101874; bh=UfsDrit7eLpVkZZfZcRzk8BZOU6gKynjWaH0yapJsnY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GBM2t+sS5avUYvRjF5rsRwgVGggc9u9dqiKiC5icg2O6vsFE3kcuoL0LOV/SgASNs jLR/49+n5k5SExlQXpUt955wZuPAfpyqh6NXvGhcP3y2wTErD34R9XoN/8nO7mimtM yRdHraNzyNHO+y50M93xQGUXRO3ItL7Tq/rxHRwgKkGd6zSNbWY5GW8Iyd0u9e6ea0 s2RMYNMTxusmxsXDu5QVy6XoYTqQ+b07TFH57zBzemu0cFnLFL3owUehAjLorssump KL1vgktz2F5MKKj7Bw7QIh9OzmY6HzMObv0SZGW3N/rkhorTM42d0eHUOkZFoMAGh8 qwajrNOhuYLZQ== Received: from localhost (odin.codewreck.org [local]) by odin.codewreck.org (OpenSMTPD) with ESMTPA id 6bace919; Sat, 11 Feb 2023 07:50:43 +0000 (UTC) From: Dominique Martinet To: v9fs-developer@lists.sourceforge.net, Eric Van Hensbergen , Christian Schoenebeck Cc: Latchesar Ionkov , linux-kernel@vger.kernel.org, Jens Axboe , Pengfei Xu , Dominique Martinet Subject: [PATCH 1/5] 9p/net: move code in preparation of async rpc Date: Sat, 11 Feb 2023 16:50:19 +0900 Message-Id: <20230211075023.137253-2-asmadeus@codewreck.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230211075023.137253-1-asmadeus@codewreck.org> References: <20230211075023.137253-1-asmadeus@codewreck.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This commit containers no code change: - move p9_fid_* higher in code as p9_fid_destroy will be used in async callback - move p9_client_flush as it will no longer call p9_client_rpc and can simplify forward declaration a bit later This just simplifies the next commits to make diffs cleaner. Signed-off-by: Dominique Martinet Reviewed-by: Christian Schoenebeck Tested-by: Christian Schoenebeck --- net/9p/client.c | 198 ++++++++++++++++++++++++------------------------ 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 622ec6a586ee..53ebd07c36ee 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -428,6 +428,66 @@ static void p9_tag_cleanup(struct p9_client *c) rcu_read_unlock(); } =20 +static struct p9_fid *p9_fid_create(struct p9_client *clnt) +{ + int ret; + struct p9_fid *fid; + + p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt); + fid =3D kzalloc(sizeof(*fid), GFP_KERNEL); + if (!fid) + return NULL; + + fid->mode =3D -1; + fid->uid =3D current_fsuid(); + fid->clnt =3D clnt; + refcount_set(&fid->count, 1); + + idr_preload(GFP_KERNEL); + spin_lock_irq(&clnt->lock); + ret =3D idr_alloc_u32(&clnt->fids, fid, &fid->fid, P9_NOFID - 1, + GFP_NOWAIT); + spin_unlock_irq(&clnt->lock); + idr_preload_end(); + if (!ret) { + trace_9p_fid_ref(fid, P9_FID_REF_CREATE); + return fid; + } + + kfree(fid); + return NULL; +} + +static void p9_fid_destroy(struct p9_fid *fid) +{ + struct p9_client *clnt; + unsigned long flags; + + p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid); + trace_9p_fid_ref(fid, P9_FID_REF_DESTROY); + clnt =3D fid->clnt; + spin_lock_irqsave(&clnt->lock, flags); + idr_remove(&clnt->fids, fid->fid); + spin_unlock_irqrestore(&clnt->lock, flags); + kfree(fid->rdir); + kfree(fid); +} + +/* We also need to export tracepoint symbols for tracepoint_enabled() */ +EXPORT_TRACEPOINT_SYMBOL(9p_fid_ref); + +void do_trace_9p_fid_get(struct p9_fid *fid) +{ + trace_9p_fid_ref(fid, P9_FID_REF_GET); +} +EXPORT_SYMBOL(do_trace_9p_fid_get); + +void do_trace_9p_fid_put(struct p9_fid *fid) +{ + trace_9p_fid_ref(fid, P9_FID_REF_PUT); +} +EXPORT_SYMBOL(do_trace_9p_fid_put); + /** * p9_client_cb - call back from transport to client * @c: client state @@ -570,6 +630,45 @@ static int p9_check_errors(struct p9_client *c, struct= p9_req_t *req) return err; } =20 +static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, + int8_t type, uint t_size, uint r_size, + const char *fmt, va_list ap) +{ + int err; + struct p9_req_t *req; + va_list apc; + + p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type); + + /* we allow for any status other than disconnected */ + if (c->status =3D=3D Disconnected) + return ERR_PTR(-EIO); + + /* if status is begin_disconnected we allow only clunk request */ + if (c->status =3D=3D BeginDisconnect && type !=3D P9_TCLUNK) + return ERR_PTR(-EIO); + + va_copy(apc, ap); + req =3D p9_tag_alloc(c, type, t_size, r_size, fmt, apc); + va_end(apc); + if (IS_ERR(req)) + return req; + + /* marshall the data */ + p9pdu_prepare(&req->tc, req->tc.tag, type); + err =3D p9pdu_vwritef(&req->tc, c->proto_version, fmt, ap); + if (err) + goto reterr; + p9pdu_finalize(c, &req->tc); + trace_9p_client_req(c, type, req->tc.tag); + return req; +reterr: + p9_req_put(c, req); + /* We have to put also the 2nd reference as it won't be used */ + p9_req_put(c, req); + return ERR_PTR(err); +} + static struct p9_req_t * p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); =20 @@ -613,45 +712,6 @@ static int p9_client_flush(struct p9_client *c, struct= p9_req_t *oldreq) return 0; } =20 -static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, - int8_t type, uint t_size, uint r_size, - const char *fmt, va_list ap) -{ - int err; - struct p9_req_t *req; - va_list apc; - - p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type); - - /* we allow for any status other than disconnected */ - if (c->status =3D=3D Disconnected) - return ERR_PTR(-EIO); - - /* if status is begin_disconnected we allow only clunk request */ - if (c->status =3D=3D BeginDisconnect && type !=3D P9_TCLUNK) - return ERR_PTR(-EIO); - - va_copy(apc, ap); - req =3D p9_tag_alloc(c, type, t_size, r_size, fmt, apc); - va_end(apc); - if (IS_ERR(req)) - return req; - - /* marshall the data */ - p9pdu_prepare(&req->tc, req->tc.tag, type); - err =3D p9pdu_vwritef(&req->tc, c->proto_version, fmt, ap); - if (err) - goto reterr; - p9pdu_finalize(c, &req->tc); - trace_9p_client_req(c, type, req->tc.tag); - return req; -reterr: - p9_req_put(c, req); - /* We have to put also the 2nd reference as it won't be used */ - p9_req_put(c, req); - return ERR_PTR(err); -} - /** * p9_client_rpc - issue a request and wait for a response * @c: client session @@ -838,66 +898,6 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_cli= ent *c, int8_t type, return ERR_PTR(safe_errno(err)); } =20 -static struct p9_fid *p9_fid_create(struct p9_client *clnt) -{ - int ret; - struct p9_fid *fid; - - p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt); - fid =3D kzalloc(sizeof(*fid), GFP_KERNEL); - if (!fid) - return NULL; - - fid->mode =3D -1; - fid->uid =3D current_fsuid(); - fid->clnt =3D clnt; - refcount_set(&fid->count, 1); - - idr_preload(GFP_KERNEL); - spin_lock_irq(&clnt->lock); - ret =3D idr_alloc_u32(&clnt->fids, fid, &fid->fid, P9_NOFID - 1, - GFP_NOWAIT); - spin_unlock_irq(&clnt->lock); - idr_preload_end(); - if (!ret) { - trace_9p_fid_ref(fid, P9_FID_REF_CREATE); - return fid; - } - - kfree(fid); - return NULL; -} - -static void p9_fid_destroy(struct p9_fid *fid) -{ - struct p9_client *clnt; - unsigned long flags; - - p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid); - trace_9p_fid_ref(fid, P9_FID_REF_DESTROY); - clnt =3D fid->clnt; - spin_lock_irqsave(&clnt->lock, flags); - idr_remove(&clnt->fids, fid->fid); - spin_unlock_irqrestore(&clnt->lock, flags); - kfree(fid->rdir); - kfree(fid); -} - -/* We also need to export tracepoint symbols for tracepoint_enabled() */ -EXPORT_TRACEPOINT_SYMBOL(9p_fid_ref); - -void do_trace_9p_fid_get(struct p9_fid *fid) -{ - trace_9p_fid_ref(fid, P9_FID_REF_GET); -} -EXPORT_SYMBOL(do_trace_9p_fid_get); - -void do_trace_9p_fid_put(struct p9_fid *fid) -{ - trace_9p_fid_ref(fid, P9_FID_REF_PUT); -} -EXPORT_SYMBOL(do_trace_9p_fid_put); - static int p9_client_version(struct p9_client *c) { int err =3D 0; --=20 2.39.1 From nobody Fri Sep 12 08:55:15 2025 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 47B2FC636CC for ; Sat, 11 Feb 2023 07:51:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229788AbjBKHvF (ORCPT ); Sat, 11 Feb 2023 02:51:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47242 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229764AbjBKHvB (ORCPT ); Sat, 11 Feb 2023 02:51:01 -0500 Received: from nautica.notk.org (ipv6.notk.org [IPv6:2001:41d0:1:7a93::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8C2A56EE0 for ; Fri, 10 Feb 2023 23:50:59 -0800 (PST) Received: by nautica.notk.org (Postfix, from userid 108) id DBCC6C01F; Sat, 11 Feb 2023 08:51:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101879; bh=0dG1T5rTNJj68tFKpAZu+B7hHGU13VEF6aoe1h4gpx0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RBn9QulEmLuWlHT2eRLH8T0dFTSaM2Ogzr+ibPEeADMRtJPOP1QifNtSgepbDDiaP nXYnhuEVFv65LWu8ynDOvO9KXsaGJMduer8+CFu4Quxb4x3663LVQv4wY08cNoHDPA stfbU8l8M4ZefNBlUk8MAIJoHkUijr/OTYe2c34wKKaR1X9051Rb4O8zDGGfruaIhF RY6gHvolHQOEudQkknXwJJC3tker2amohpF4n29BtorhUW186EcyrD7PofGeUzKMxB xA2VFWHQZZqRWZcsH2xjkHQi1LWJHDf6gu+NmfOvCuCONog9JaLYYN37XAlr3BHOqE B3J1riCC0LHDw== Received: from odin.codewreck.org (localhost [127.0.0.1]) by nautica.notk.org (Postfix) with ESMTPS id 2A438C01F; Sat, 11 Feb 2023 08:51:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101879; bh=0dG1T5rTNJj68tFKpAZu+B7hHGU13VEF6aoe1h4gpx0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RBn9QulEmLuWlHT2eRLH8T0dFTSaM2Ogzr+ibPEeADMRtJPOP1QifNtSgepbDDiaP nXYnhuEVFv65LWu8ynDOvO9KXsaGJMduer8+CFu4Quxb4x3663LVQv4wY08cNoHDPA stfbU8l8M4ZefNBlUk8MAIJoHkUijr/OTYe2c34wKKaR1X9051Rb4O8zDGGfruaIhF RY6gHvolHQOEudQkknXwJJC3tker2amohpF4n29BtorhUW186EcyrD7PofGeUzKMxB xA2VFWHQZZqRWZcsH2xjkHQi1LWJHDf6gu+NmfOvCuCONog9JaLYYN37XAlr3BHOqE B3J1riCC0LHDw== Received: from localhost (odin.codewreck.org [local]) by odin.codewreck.org (OpenSMTPD) with ESMTPA id 5f99bccc; Sat, 11 Feb 2023 07:50:46 +0000 (UTC) From: Dominique Martinet To: v9fs-developer@lists.sourceforge.net, Eric Van Hensbergen , Christian Schoenebeck Cc: Latchesar Ionkov , linux-kernel@vger.kernel.org, Jens Axboe , Pengfei Xu , Dominique Martinet Subject: [PATCH 2/5] 9p/net: share pooled receive buffers size exception in p9_tag_alloc Date: Sat, 11 Feb 2023 16:50:20 +0900 Message-Id: <20230211075023.137253-3-asmadeus@codewreck.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230211075023.137253-1-asmadeus@codewreck.org> References: <20230211075023.137253-1-asmadeus@codewreck.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The async RPC code will also use an automatic size and this bit of code can be shared, as p9_tag_alloc still knows what client we alloc for. Signed-off-by: Dominique Martinet Reviewed-by: Christian Schoenebeck Tested-by: Christian Schoenebeck --- net/9p/client.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 53ebd07c36ee..4e5238db4a7a 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -282,8 +282,15 @@ p9_tag_alloc(struct p9_client *c, int8_t type, uint t_= size, uint r_size, t_size ?: p9_msg_buf_size(c, type, fmt, apc)); va_end(apc); =20 - alloc_rsize =3D min_t(size_t, c->msize, - r_size ?: p9_msg_buf_size(c, type + 1, fmt, ap)); + /* Currently RDMA transport is excluded from response message size + * optimization, as it cannot cope with it due to its pooled response + * buffers (this has no impact on request size) + */ + if (r_size =3D=3D 0 && c->trans_mod->pooled_rbuffers) + alloc_rsize =3D c->msize; + else + alloc_rsize =3D min_t(size_t, c->msize, + r_size ?: p9_msg_buf_size(c, type + 1, fmt, ap)); =20 if (!req) return ERR_PTR(-ENOMEM); @@ -728,18 +735,10 @@ p9_client_rpc(struct p9_client *c, int8_t type, const= char *fmt, ...) int sigpending, err; unsigned long flags; struct p9_req_t *req; - /* Passing zero for tsize/rsize to p9_client_prepare_req() tells it to - * auto determine an appropriate (small) request/response size - * according to actual message data being sent. Currently RDMA - * transport is excluded from this response message size optimization, - * as it would not cope with it, due to its pooled response buffers - * (using an optimized request size for RDMA as well though). - */ - const uint tsize =3D 0; - const uint rsize =3D c->trans_mod->pooled_rbuffers ? c->msize : 0; =20 va_start(ap, fmt); - req =3D p9_client_prepare_req(c, type, tsize, rsize, fmt, ap); + /* auto determine an appropriate request/response size */ + req =3D p9_client_prepare_req(c, type, 0, 0, fmt, ap); va_end(ap); if (IS_ERR(req)) return req; --=20 2.39.1 From nobody Fri Sep 12 08:55:15 2025 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 77E5CC636CC for ; Sat, 11 Feb 2023 07:51:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229740AbjBKHvO (ORCPT ); Sat, 11 Feb 2023 02:51:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47656 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229710AbjBKHvM (ORCPT ); Sat, 11 Feb 2023 02:51:12 -0500 Received: from nautica.notk.org (ipv6.notk.org [IPv6:2001:41d0:1:7a93::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F25295A9EB for ; Fri, 10 Feb 2023 23:51:04 -0800 (PST) Received: by nautica.notk.org (Postfix, from userid 108) id 0EBDDC01C; Sat, 11 Feb 2023 08:51:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101885; bh=1ZCkzS/1FJu9PN2kIb6WCyEHTHdTNKRX/Kb4Z8zBiuU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cS2UNnl6FBlB4ONZ/M5zBftk3kPQAv8FWhBmucPwq90iIOevATkm+6VQRzg0uWClF JHSxBoM3Y8vCEX4WnsJNudWhFW0xEMDjasnbU0WW1C/wKNQHRAlQR09V2WQPufy+Mj Qid4sTB98ohZhbIn3vQkFOh+IiiuNCrA6iMmCpw9x7J7XNmu+tlty0Sa77AYJTky4n BVOP2PwaMaaoeaS3J3Wr015Xyugjgd6hS+d5gFZ2k8Ng4xSLHumOn6VoHEY2cDcbP7 u9NFsGms84TNFwqIoOOF9NVTC5v+Uq5o/TH2yPM2AwFP39HaE+wG1Gkkcal8Cv2ahc mKpw6QwwzYQ0g== Received: from odin.codewreck.org (localhost [127.0.0.1]) by nautica.notk.org (Postfix) with ESMTPS id 1DE1DC01A; Sat, 11 Feb 2023 08:51:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101883; bh=1ZCkzS/1FJu9PN2kIb6WCyEHTHdTNKRX/Kb4Z8zBiuU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X4NQ6MeXwb+i+vda9m4Q9nZoPwdd0RNT2LU5zT2URgRjLPnX9aBfc9Hm3kzd9wAF3 Fv7MrG6ZSh4ZGjXUtqP9OYbtO9Snyj7zauP5VPtEdnsv0/5uq72JvpUYGF/OsghjMD c5XPJKiDY2sfqwf8HKm3OJ7PuU2tomjh+sACG+Gk8TUu5UPMLVbJ2oOakHh6hdujgM ZlHJ9gt0VNDEjxnENVwqTD2MFjB2ZlfMPvPOzXIk9vItLemK8g+wF78dF4ukQgZIG9 LNJNs5SMeQhIKaiBiea55MPHNDGNOx9xWZJkmN1nwBr1feRLngzG32TPyMqW7M/g8U pwi7+YwKK73ZA== Received: from localhost (odin.codewreck.org [local]) by odin.codewreck.org (OpenSMTPD) with ESMTPA id 6d213fc5; Sat, 11 Feb 2023 07:50:46 +0000 (UTC) From: Dominique Martinet To: v9fs-developer@lists.sourceforge.net, Eric Van Hensbergen , Christian Schoenebeck Cc: Latchesar Ionkov , linux-kernel@vger.kernel.org, Jens Axboe , Pengfei Xu , Dominique Martinet Subject: [PATCH 3/5] 9p/net: implement asynchronous rpc skeleton Date: Sat, 11 Feb 2023 16:50:21 +0900 Message-Id: <20230211075023.137253-4-asmadeus@codewreck.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230211075023.137253-1-asmadeus@codewreck.org> References: <20230211075023.137253-1-asmadeus@codewreck.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add p9_client_async_rpc that will let us send an rpc without waiting for the reply, as well as an async callback hook. The callback is called, but nothing is ever put in the list at this point and p9_client_async_rpc() is unused. Previous version of this patch here[1] used to implement the async check separately from the callback, but we will want to be notified when flush has been processed. Link: http://lkml.kernel.org/r/1544532108-21689-1-git-send-email-asmadeus@c= odewreck.org (v1) Signed-off-by: Dominique Martinet Tested-by: Christian Schoenebeck --- include/net/9p/client.h | 9 ++++- net/9p/client.c | 76 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 78ebcf782ce5..348ea191ac66 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -72,7 +72,8 @@ enum p9_req_status_t { * @wq: wait_queue for the client to block on for this request * @tc: the request fcall structure * @rc: the response fcall structure - * @req_list: link for higher level objects to chain requests + * @req_list: link for transports to chain requests (used by trans_fd) + * @async_list: link used to check on async requests */ struct p9_req_t { int status; @@ -82,6 +83,7 @@ struct p9_req_t { struct p9_fcall tc; struct p9_fcall rc; struct list_head req_list; + struct list_head async_list; }; =20 /** @@ -92,6 +94,9 @@ struct p9_req_t { * @trans_mod: module API instantiated with this client * @status: connection state * @trans: tranport instance state and API + * @fcall_cache: kmem cache for client request data (msize-specific) + * @async_req_lock: protects @async_req_list + * @async_req_list: list of requests waiting a reply * @fids: All active FID handles * @reqs: All active requests. * @name: node name used as client id @@ -107,6 +112,8 @@ struct p9_client { enum p9_trans_status status; void *trans; struct kmem_cache *fcall_cache; + spinlock_t async_req_lock; + struct list_head async_req_list; =20 union { struct { diff --git a/net/9p/client.c b/net/9p/client.c index 4e5238db4a7a..3235543c1884 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -311,6 +311,7 @@ p9_tag_alloc(struct p9_client *c, int8_t type, uint t_s= ize, uint r_size, refcount_set(&req->refcount, 0); init_waitqueue_head(&req->wq); INIT_LIST_HEAD(&req->req_list); + INIT_LIST_HEAD(&req->async_list); =20 idr_preload(GFP_NOFS); spin_lock_irq(&c->lock); @@ -495,6 +496,27 @@ void do_trace_9p_fid_put(struct p9_fid *fid) } EXPORT_SYMBOL(do_trace_9p_fid_put); =20 +/** + * p9_client_async_cb -- handle async requests in cb + * @c: client state + * @req: request received + */ +static void p9_client_async_cb(struct p9_client *c, struct p9_req_t *req) +{ + unsigned long flags; + + /* Nothing to do for non-async requests */ + if (likely(list_empty(&req->async_list))) + return; + + WARN(1, "Async request received with tc.id %d\n", req->tc.id); + + spin_lock_irqsave(&c->async_req_lock, flags); + list_del(&req->async_list); + spin_unlock_irqrestore(&c->async_req_lock, flags); + p9_tag_remove(c, req); +} + /** * p9_client_cb - call back from transport to client * @c: client state @@ -506,6 +528,8 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t = *req, int status) { p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc.tag); =20 + p9_client_async_cb(c, req); + /* This barrier is needed to make sure any change made to req before * the status change is visible to another thread */ @@ -676,6 +700,54 @@ static struct p9_req_t *p9_client_prepare_req(struct p= 9_client *c, return ERR_PTR(err); } =20 +static struct p9_req_t * +p9_client_async_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) +{ + va_list ap; + int err; + struct p9_req_t *req; + + va_start(ap, fmt); + /* auto determine an appropriate request/response size */ + req =3D p9_client_prepare_req(c, type, 0, 0, fmt, ap); + va_end(ap); + if (IS_ERR(req)) + return req; + + err =3D c->trans_mod->request(c, req); + if (err < 0) { + /* bail out without flushing... */ + p9_req_put(c, req); + p9_tag_remove(c, req); + if (err !=3D -ERESTARTSYS && err !=3D -EFAULT) + c->status =3D Disconnected; + return ERR_PTR(safe_errno(err)); + } + + return req; +} + +static void p9_client_cleanup_async(struct p9_client *c) +{ + struct p9_req_t *req, *nreq; + unsigned long flags; + + spin_lock_irqsave(&c->async_req_lock, flags); + list_for_each_entry_safe(req, nreq, &c->async_req_list, async_list) { + if (req->status < REQ_STATUS_RCVD) { + p9_debug(P9_DEBUG_ERROR, + "final async handler found req tag %d type %d status %d\n", + req->tc.tag, req->tc.id, req->status); + if (c->trans_mod->cancelled) + c->trans_mod->cancelled(c, req); + /* won't receive reply now */ + p9_req_put(c, req); + } + p9_client_async_cb(c, req); + } + spin_unlock_irqrestore(&c->async_req_lock, flags); +} + static struct p9_req_t * p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); =20 @@ -983,6 +1055,8 @@ struct p9_client *p9_client_create(const char *dev_nam= e, char *options) memcpy(clnt->name, client_id, strlen(client_id) + 1); =20 spin_lock_init(&clnt->lock); + spin_lock_init(&clnt->async_req_lock); + INIT_LIST_HEAD(&clnt->async_req_list); idr_init(&clnt->fids); idr_init(&clnt->reqs); =20 @@ -1059,6 +1133,8 @@ void p9_client_destroy(struct p9_client *clnt) =20 v9fs_put_trans(clnt->trans_mod); =20 + p9_client_cleanup_async(clnt); + idr_for_each_entry(&clnt->fids, fid, id) { pr_info("Found fid %d not clunked\n", fid->fid); p9_fid_destroy(fid); --=20 2.39.1 From nobody Fri Sep 12 08:55:15 2025 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 C0BA4C636CC for ; Sat, 11 Feb 2023 07:51:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229787AbjBKHvR (ORCPT ); Sat, 11 Feb 2023 02:51:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229457AbjBKHvO (ORCPT ); Sat, 11 Feb 2023 02:51:14 -0500 Received: from nautica.notk.org (ipv6.notk.org [IPv6:2001:41d0:1:7a93::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4984171007 for ; Fri, 10 Feb 2023 23:51:06 -0800 (PST) Received: by nautica.notk.org (Postfix, from userid 108) id 023FDC026; Sat, 11 Feb 2023 08:51:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101886; bh=Awb21O0vXpVV+2crD+UEksVt5c15/VZc1nIv355OlHo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e9514OBk1mSoo/s8WQMymBl6Xc/ZKaL2FdUfe24zNFVju1sAU+NQA7KTKkWTzD0Sw H4HITxIvKHRbesBKUELbh6iNn3pfH0eI9fM1tDt0V+EOGCu5kSkx1IPCNc+T+U6WQF 2yHc+Kd7+4Y7VWBUtuKSazK2wY/4B+Blo7Nap1xGN6dQbrH4XSx+5JdXhcA+52mCbD YQW7AkpMGfjcQBVShK7Zj80j/UFg1oaZrnXWVBMvS8QInk3X4DZIzIxV0zyjfon2+R c5C8LeuSghdVumUCbT9wuckwmuuAs28ESKZYtSF5t5BIOxflPHywyESOOlLCLpSe94 A7DqMZ0E1TiNg== Received: from odin.codewreck.org (localhost [127.0.0.1]) by nautica.notk.org (Postfix) with ESMTPS id 28B5AC01B; Sat, 11 Feb 2023 08:51:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101884; bh=Awb21O0vXpVV+2crD+UEksVt5c15/VZc1nIv355OlHo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hBDLiok5J97wnV0H5zWJEcW2GYHKuGikXzDPe/NfEX/AtWDbRLsRn9Xc9jDr9vrt4 BQg+udlqJgkQxFy0l8P7QpLcx0MjT7bczG3Ol2eUgMFifO4AGSc6pV+kefLATJV4g3 3wkmNXKzkFZ0EQr4RsSMH/2gBqbCupE5lx3U74JQu85cBwA3Tdcn5wl1fs0Iwq3GqD 3Ol9ZTUKcvqKu1igt7yP13gk9Nwrz6bcapRQZPCCI+DOaZ9Y9nbExVNqRhaTZGDPO5 NNW+b+hojqQx0wE7Es5mKWiQDbQ6Juh95RtM9OZAg7bbFnr1jg9BDRzl8HQhtV7TWb V64HpXvohmZvg== Received: from localhost (odin.codewreck.org [local]) by odin.codewreck.org (OpenSMTPD) with ESMTPA id 6c15f3d7; Sat, 11 Feb 2023 07:50:47 +0000 (UTC) From: Dominique Martinet To: v9fs-developer@lists.sourceforge.net, Eric Van Hensbergen , Christian Schoenebeck Cc: Latchesar Ionkov , linux-kernel@vger.kernel.org, Jens Axboe , Pengfei Xu , Dominique Martinet Subject: [PATCH 4/5] 9p/net: add async clunk for retries Date: Sat, 11 Feb 2023 16:50:22 +0900 Message-Id: <20230211075023.137253-5-asmadeus@codewreck.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230211075023.137253-1-asmadeus@codewreck.org> References: <20230211075023.137253-1-asmadeus@codewreck.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" clunks in 9p are absolute: once the request is sent to the server, the local end should consider the fid freed. Unfortunately our retry logic is hazardous at best, if we got ERESTARTSYS and we call p9_client_rpc again odds are we'll just notice the same signal is pending again and fail, leaking the fd. This used to work, because we never actually got to second retry with the flush logic, as most servers ignore the flush request and send the clunk reply first, in which case p9_client_rpc() will return successfully even if it got interrupted. Once async flush come into play we will start leaking fids everytime a task is interrupted, avoid this by resending the flush and handling it asynchronously. Note that it's possible that the server got the clunk twice, but it will be a clunk for a fid that is not used (client controls fid number allocation), and the async cb does not consider the client return value. We do not make all clunks asynchronous because some tests failed when this was tried in [1] ; clunk in 9p should not act like a barrier like close() does (e.g. flushing contents) but I have no time to debug. This might still be a problem with the retries, but we are still better than the current code which gives up and leaks the fid. What should probably be done next is to make all calls to p9_fid_put check for errors, at which point the failed clunk can be returned as an error to userspace which could then notice the error. (Not like most programs check for close() return value in the first place...) Link: http://lkml.kernel.org/r/1544532108-21689-2-git-send-email-asmadeus@c= odewreck.org [1] Signed-off-by: Dominique Martinet Tested-by: Christian Schoenebeck --- include/net/9p/client.h | 4 +++ net/9p/client.c | 58 ++++++++++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 348ea191ac66..dd493f7b8059 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -74,6 +74,7 @@ enum p9_req_status_t { * @rc: the response fcall structure * @req_list: link for transports to chain requests (used by trans_fd) * @async_list: link used to check on async requests + * @clunked_fid: for clunk, points to fid */ struct p9_req_t { int status; @@ -84,6 +85,9 @@ struct p9_req_t { struct p9_fcall rc; struct list_head req_list; struct list_head async_list; + union { + struct p9_fid *clunked_fid; + }; }; =20 /** diff --git a/net/9p/client.c b/net/9p/client.c index 3235543c1884..f4b85c33c465 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -509,7 +509,13 @@ static void p9_client_async_cb(struct p9_client *c, st= ruct p9_req_t *req) if (likely(list_empty(&req->async_list))) return; =20 - WARN(1, "Async request received with tc.id %d\n", req->tc.id); + if (req->tc.id =3D=3D P9_TCLUNK) { + p9_debug(P9_DEBUG_MUX, "async destroying fid %d\n", + req->clunked_fid->fid); + p9_fid_destroy(req->clunked_fid); + } else { + WARN(1, "Async request received with tc.id %d\n", req->tc.id); + } =20 spin_lock_irqsave(&c->async_req_lock, flags); list_del(&req->async_list); @@ -1497,16 +1503,35 @@ int p9_client_fsync(struct p9_fid *fid, int datasyn= c) } EXPORT_SYMBOL(p9_client_fsync); =20 +static int p9_client_async_clunk(struct p9_fid *fid) +{ + struct p9_client *clnt; + struct p9_req_t *req; + + p9_debug(P9_DEBUG_9P, ">>> async TCLUNK fid %d\n", fid->fid); + clnt =3D fid->clnt; + + req =3D p9_client_async_rpc(clnt, P9_TCLUNK, "d", fid->fid); + if (IS_ERR(req)) { + /* leak fid until umount... */ + return PTR_ERR(req); + } + + req->clunked_fid =3D fid; + spin_lock_irq(&clnt->lock); + list_add(&req->async_list, &clnt->async_req_list); + spin_unlock_irq(&clnt->lock); + + return 0; +} + int p9_client_clunk(struct p9_fid *fid) { int err; struct p9_client *clnt; struct p9_req_t *req; - int retries =3D 0; =20 -again: - p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", - fid->fid, retries); + p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); err =3D 0; clnt =3D fid->clnt; =20 @@ -1520,16 +1545,23 @@ int p9_client_clunk(struct p9_fid *fid) =20 p9_req_put(clnt, req); error: - /* Fid is not valid even after a failed clunk - * If interrupted, retry once then give up and - * leak fid until umount. + /* Fid is not valid even after a failed clunk, but we do not + * know if we successfully sent the request so send again + * asynchronously ('err' cannot differentiate between: + * failure on the client side before send, interrupted + * before we sent the request, interrupted after we sent + * the request and error from the server) + * In doubt it's better to try to ask again (for the + * 'interrupted before we sent the request' case), other + * patterns will just ignore again. + * Return the original error though. */ - if (err =3D=3D -ERESTARTSYS) { - if (retries++ =3D=3D 0) - goto again; - } else { - p9_fid_destroy(fid); + if (err) { + p9_client_async_clunk(fid); + return err; } + + p9_fid_destroy(fid); return err; } EXPORT_SYMBOL(p9_client_clunk); --=20 2.39.1 From nobody Fri Sep 12 08:55:15 2025 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 4033AC636CC for ; Sat, 11 Feb 2023 07:51:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229550AbjBKHv2 (ORCPT ); Sat, 11 Feb 2023 02:51:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48114 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229764AbjBKHv0 (ORCPT ); Sat, 11 Feb 2023 02:51:26 -0500 Received: from nautica.notk.org (ipv6.notk.org [IPv6:2001:41d0:1:7a93::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0897A63580 for ; Fri, 10 Feb 2023 23:51:11 -0800 (PST) Received: by nautica.notk.org (Postfix, from userid 108) id E0ECDC01E; Sat, 11 Feb 2023 08:51:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101891; bh=+UMZTOAl7PgxJc9ldQNYn/dq+/3fCg8KJj367+x2Kwo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KxOxIb8aRgK+IGt78uvFeRBgpnkMSw8q45yU5jfU1XFMhVJhfzYAVv7DZ3kIe0KvQ y7cCs+/oRhYwmRtembKTO5WO6Ld6lPcZHTFkXvjQHPhQtScliBixXTemD1ff+/e+dr RD/Aqu8tybfQKiE7AwLQkeQbYi8TN7UdNFu2wWOCJKRA1ONF5saewdGkF95ohzuGD9 QlaG690CYbdQYvIRmNEFWyjdAPRncMyebK2GYS0CGMG9ABwHJnsbFUzm22/PILkAot MGh1Aj0qhoDhSi8y46DhXix3Jg3QaMctPhu3GudE6a92qiE+ysPZrNO4xLvw2lcBJR WmGIymSR33fjw== Received: from odin.codewreck.org (localhost [127.0.0.1]) by nautica.notk.org (Postfix) with ESMTPS id D3AF0C01F; Sat, 11 Feb 2023 08:51:24 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codewreck.org; s=2; t=1676101889; bh=+UMZTOAl7PgxJc9ldQNYn/dq+/3fCg8KJj367+x2Kwo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tklAVM4XKDVG4gf899kWFcDDQu+r2Ed5oKmTpMSTD0ICtrSkdi4zblHJ4Qw2f3YRC 4dZiqJHetIIejJy4yLudKlSRtS0bxw2pmmSqP9RrtMbvg5NU4csfYFPTWGApu2/RvO HXx9s7tn8bkiI4W4NmdAY7xi2rXPuK6LL9WkeY6bucfqJ5+FFnV3QB8YxSPdjN4VWr RO0o5PHuulAsp4Jvz15qhBnqXz7Si29CdfRCa3Z0V61IS5rmo1n0O+azVq37/ZHXmt RlEagldeYqgd1MVQfrepN5LKmWnNSUazRSBMWZKRxU9SyFm71xH+YXfVn60sRmUTc5 uzXSn9qqquVaA== Received: from localhost (odin.codewreck.org [local]) by odin.codewreck.org (OpenSMTPD) with ESMTPA id 53778030; Sat, 11 Feb 2023 07:50:48 +0000 (UTC) From: Dominique Martinet To: v9fs-developer@lists.sourceforge.net, Eric Van Hensbergen , Christian Schoenebeck Cc: Latchesar Ionkov , linux-kernel@vger.kernel.org, Jens Axboe , Pengfei Xu , Dominique Martinet , Dmitry Vyukov Subject: [PATCH 5/5] 9p/net: make flush asynchronous Date: Sat, 11 Feb 2023 16:50:23 +0900 Message-Id: <20230211075023.137253-6-asmadeus@codewreck.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230211075023.137253-1-asmadeus@codewreck.org> References: <20230211075023.137253-1-asmadeus@codewreck.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Make the client flush asynchronous so we don't need to ignore signals in rpc functions: - on signal, send a flush request as we previously did but use the new asynchronous helper and return immediately - when the reply has been received or connection is destroyed, free both tags in the handler Since the 9p client has no way of knowing if a request has been replayed after flush, we also need to wait for all flush to have been processed in order to avoid the following example scenario: 1. Send write#1 [0; 1MB[ 2. Receive signal and interrupt the write, code sends flush and return 3. Resend write as write#2 [0; 1MB[ 4. write#2 is handled 5. Send write#3 [1MB-4k; 1MB[ 6. write#3 is handled 7. write#1 is handled and write#3's content overwritten (flush is later ack'd) In practice, all transports use a connection-oriented pipe (e.g. messages are received in order), so requests are guaranteed to be received by the server in the order they were sent; but the server has no way of knowing that the second write is a replay of the first and could be dispatched to another thread leading to such scenario. This means the connection is effectively put on hold after any flush has been sent, but hopefully flush are rare enough to not make a difference in normal workloads. Not looping forever in p9_client_rpc and its zc counterpart has been a goal for a long time, but will also in particular fix a new hang with the TWA_SIGNAL based task_work as reported by Pengfei Xu and Jens Axboe recently. Reported-by: Dmitry Vyukov Reported-by: Pengfei Xu Reported-by: Jens Axboe Link: http://lkml.kernel.org/r/1544532108-21689-3-git-send-email-asmadeus@c= odewreck.org (v1) Signed-off-by: Dominique Martinet Tested-by: Christian Schoenebeck --- include/net/9p/client.h | 2 + net/9p/client.c | 187 ++++++++++++++++++++++++---------------- 2 files changed, 113 insertions(+), 76 deletions(-) diff --git a/include/net/9p/client.h b/include/net/9p/client.h index dd493f7b8059..9eec67108096 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -75,6 +75,7 @@ enum p9_req_status_t { * @req_list: link for transports to chain requests (used by trans_fd) * @async_list: link used to check on async requests * @clunked_fid: for clunk, points to fid + * @flushed_req: for flush, points to matching flushed req */ struct p9_req_t { int status; @@ -87,6 +88,7 @@ struct p9_req_t { struct list_head async_list; union { struct p9_fid *clunked_fid; + struct p9_req_t *flushed_req; }; }; =20 diff --git a/net/9p/client.c b/net/9p/client.c index f4b85c33c465..4c328021dc98 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -503,6 +503,8 @@ EXPORT_SYMBOL(do_trace_9p_fid_put); */ static void p9_client_async_cb(struct p9_client *c, struct p9_req_t *req) { + /* extra req to put e.g. flush target */ + struct p9_req_t *extra_req =3D NULL; unsigned long flags; =20 /* Nothing to do for non-async requests */ @@ -513,14 +515,31 @@ static void p9_client_async_cb(struct p9_client *c, s= truct p9_req_t *req) p9_debug(P9_DEBUG_MUX, "async destroying fid %d\n", req->clunked_fid->fid); p9_fid_destroy(req->clunked_fid); + } else if (req->tc.id =3D=3D P9_TFLUSH) { + p9_debug(P9_DEBUG_MUX, + "flushing oldreq tag %d status %d, flush_req tag %d\n", + req->flushed_req->tc.tag, + req->flushed_req->status, + req->tc.tag); + if (req->flushed_req->status < REQ_STATUS_RCVD) { + /* won't receive reply now */ + if (c->trans_mod->cancelled) + c->trans_mod->cancelled(c, req); + wake_up_all(&req->flushed_req->wq); + p9_req_put(c, req->flushed_req); + } + extra_req =3D req->flushed_req; } else { WARN(1, "Async request received with tc.id %d\n", req->tc.id); } - + /* Put old refs whatever reqs actually returned */ spin_lock_irqsave(&c->async_req_lock, flags); list_del(&req->async_list); spin_unlock_irqrestore(&c->async_req_lock, flags); p9_tag_remove(c, req); + + if (extra_req) + p9_req_put(c, extra_req); } =20 /** @@ -542,7 +561,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t = *req, int status) smp_wmb(); WRITE_ONCE(req->status, status); =20 - wake_up(&req->wq); + wake_up_all(&req->wq); p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag); p9_req_put(c, req); } @@ -754,9 +773,6 @@ static void p9_client_cleanup_async(struct p9_client *c) spin_unlock_irqrestore(&c->async_req_lock, flags); } =20 -static struct p9_req_t * -p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); - /** * p9_client_flush - flush (cancel) a request * @c: client state @@ -772,28 +788,68 @@ p9_client_rpc(struct p9_client *c, int8_t type, const= char *fmt, ...); static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) { struct p9_req_t *req; - s16 oldtag; - int err; - - err =3D p9_parse_header(&oldreq->tc, NULL, NULL, &oldtag, 1); - if (err) - return err; + s16 oldtag =3D oldreq->tc.tag; =20 p9_debug(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag); - - req =3D p9_client_rpc(c, P9_TFLUSH, "w", oldtag); + req =3D p9_client_async_rpc(c, P9_TFLUSH, "w", oldtag); if (IS_ERR(req)) return PTR_ERR(req); =20 - /* if we haven't received a response for oldreq, - * remove it from the list - */ - if (READ_ONCE(oldreq->status) =3D=3D REQ_STATUS_SENT) { - if (c->trans_mod->cancelled) - c->trans_mod->cancelled(c, oldreq); - } + p9_debug(P9_DEBUG_MUX, "sent flush for oldreq %d type %d with flush tag %= d\n", + oldtag, oldreq->tc.id, req->tc.tag); + req->flushed_req =3D oldreq; + spin_lock_irq(&c->lock); + list_add(&req->async_list, &c->async_req_list); + spin_unlock_irq(&c->lock); =20 - p9_req_put(c, req); + return 0; +} + +/** + * p9_client_wait_flush - wait for any in flight flush + * @c: client state + * + * Since we cannot know if a request is a replay for a request that was + * previous flushed, we need to wait for all in flight flush to send + * new requests to avoid racing with a previously cancelled flush. + */ + +static int p9_client_wait_flush(struct p9_client *c) +{ + struct p9_req_t *req; + unsigned long flags; + int err; + + /* As an optimization check if list is empty without lock first; + * that should be the case most of the time, and if we see it + * as empty we are not a thread that recently issued a flush + */ + if (list_empty(&c->async_req_list)) + return 0; + +again: + spin_lock_irqsave(&c->async_req_lock, flags); + list_for_each_entry(req, &c->async_req_list, async_list) { + /* received request will be deleted shortly and can be ignored */ + if (req->status >=3D REQ_STATUS_RCVD) + continue; + + if (req->tc.id =3D=3D P9_TFLUSH) { + /* also ok if its target has been ack'd */ + if (req->flushed_req->status >=3D REQ_STATUS_RCVD) + continue; + /* take ref on flushed req, drop lock and wait for it... */ + p9_req_get(req->flushed_req); + spin_unlock_irqrestore(&c->async_req_lock, flags); + err =3D wait_event_interruptible(req->flushed_req->wq, + READ_ONCE(req->status) >=3D REQ_STATUS_RCVD); + p9_req_put(c, req->flushed_req); + if (err < 0) + return err; + goto again; + } + } + spin_unlock_irqrestore(&c->async_req_lock, flags); return 0; } =20 @@ -810,8 +866,8 @@ static struct p9_req_t * p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) { va_list ap; - int sigpending, err; - unsigned long flags; + int err; + int flushing =3D 0; struct p9_req_t *req; =20 va_start(ap, fmt); @@ -825,21 +881,21 @@ p9_client_rpc(struct p9_client *c, int8_t type, const= char *fmt, ...) req->rc.zc =3D false; =20 if (signal_pending(current)) { - sigpending =3D 1; - clear_thread_flag(TIF_SIGPENDING); - } else { - sigpending =3D 0; + err =3D -ERESTARTSYS; + goto not_sent; } =20 + err =3D p9_client_wait_flush(c); + if (err < 0) + goto not_sent; + err =3D c->trans_mod->request(c, req); if (err < 0) { - /* write won't happen */ - p9_req_put(c, req); if (err !=3D -ERESTARTSYS && err !=3D -EFAULT) c->status =3D Disconnected; - goto recalc_sigpending; + goto not_sent; } -again: + /* Wait for the response */ err =3D wait_event_killable(req->wq, READ_ONCE(req->status) >=3D REQ_STATUS_RCVD); @@ -849,34 +905,15 @@ p9_client_rpc(struct p9_client *c, int8_t type, const= char *fmt, ...) */ smp_rmb(); =20 - if (err =3D=3D -ERESTARTSYS && c->status =3D=3D Connected && - type =3D=3D P9_TFLUSH) { - sigpending =3D 1; - clear_thread_flag(TIF_SIGPENDING); - goto again; - } - - if (READ_ONCE(req->status) =3D=3D REQ_STATUS_ERROR) { + if (req->status =3D=3D REQ_STATUS_ERROR) { p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); err =3D req->t_err; } if (err =3D=3D -ERESTARTSYS && c->status =3D=3D Connected) { p9_debug(P9_DEBUG_MUX, "flushing\n"); - sigpending =3D 1; - clear_thread_flag(TIF_SIGPENDING); =20 - if (c->trans_mod->cancel(c, req)) - p9_client_flush(c, req); - - /* if we received the response anyway, don't signal error */ - if (READ_ONCE(req->status) =3D=3D REQ_STATUS_RCVD) - err =3D 0; - } -recalc_sigpending: - if (sigpending) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); + if (c->trans_mod->cancel(c, req) && !p9_client_flush(c, req)) + flushing =3D 1; } if (err < 0) goto reterr; @@ -885,8 +922,12 @@ p9_client_rpc(struct p9_client *c, int8_t type, const = char *fmt, ...) trace_9p_client_res(c, type, req->rc.tag, err); if (!err) return req; -reterr: + goto reterr; +not_sent: p9_req_put(c, req); +reterr: + if (!flushing) + p9_req_put(c, req); return ERR_PTR(safe_errno(err)); } =20 @@ -910,8 +951,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_clie= nt *c, int8_t type, const char *fmt, ...) { va_list ap; - int sigpending, err; - unsigned long flags; + int err; + int flushing =3D 0; struct p9_req_t *req; =20 va_start(ap, fmt); @@ -927,19 +968,21 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_cl= ient *c, int8_t type, req->rc.zc =3D true; =20 if (signal_pending(current)) { - sigpending =3D 1; - clear_thread_flag(TIF_SIGPENDING); - } else { - sigpending =3D 0; + err =3D -ERESTARTSYS; + goto not_sent; } =20 + err =3D p9_client_wait_flush(c); + if (err < 0) + goto not_sent; + err =3D c->trans_mod->zc_request(c, req, uidata, uodata, inlen, olen, in_hdrlen); if (err < 0) { if (err =3D=3D -EIO) c->status =3D Disconnected; if (err !=3D -ERESTARTSYS) - goto recalc_sigpending; + goto not_sent; } if (READ_ONCE(req->status) =3D=3D REQ_STATUS_ERROR) { p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); @@ -947,21 +990,9 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_cli= ent *c, int8_t type, } if (err =3D=3D -ERESTARTSYS && c->status =3D=3D Connected) { p9_debug(P9_DEBUG_MUX, "flushing\n"); - sigpending =3D 1; - clear_thread_flag(TIF_SIGPENDING); =20 - if (c->trans_mod->cancel(c, req)) - p9_client_flush(c, req); - - /* if we received the response anyway, don't signal error */ - if (READ_ONCE(req->status) =3D=3D REQ_STATUS_RCVD) - err =3D 0; - } -recalc_sigpending: - if (sigpending) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); + if (c->trans_mod->cancel(c, req) && !p9_client_flush(c, req)) + flushing =3D 1; } if (err < 0) goto reterr; @@ -970,8 +1001,12 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_cl= ient *c, int8_t type, trace_9p_client_res(c, type, req->rc.tag, err); if (!err) return req; -reterr: + goto reterr; +not_sent: p9_req_put(c, req); +reterr: + if (!flushing) + p9_req_put(c, req); return ERR_PTR(safe_errno(err)); } =20 --=20 2.39.1