From patchwork Sat Nov 13 02:32:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 1554627 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=OxJd9fpq; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4HrfcP3tl9z9sCD for ; Sat, 13 Nov 2021 13:32:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232113AbhKMCfI (ORCPT ); Fri, 12 Nov 2021 21:35:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231618AbhKMCfH (ORCPT ); Fri, 12 Nov 2021 21:35:07 -0500 Received: from mail-lj1-x236.google.com (mail-lj1-x236.google.com [IPv6:2a00:1450:4864:20::236]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CCF66C061766 for ; Fri, 12 Nov 2021 18:32:15 -0800 (PST) Received: by mail-lj1-x236.google.com with SMTP id 207so21996668ljf.10 for ; Fri, 12 Nov 2021 18:32:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:from:date:message-id:subject:to:cc; bh=/KKi9MlyC2ajPTEhQDnm5E6c9PeX2Yx/QSrAgq67sV0=; b=OxJd9fpqtVno0h0eJ7fckCGLqc6vVmJSWP+3RZt5RJkWnOR0A/UMEbBK0P5PCL0xfd R4FJopp8JeV4EnEXef/cj40WRyOWQvz+4WdzNnuOo3a6yUSOUanSk6a8fNaUE+ZB2THA gNPl7cEMPGTcI5fe3cb6wNjhpF9PiQ651/AGkOAT3AXk/GeftkBNfyzUoV3sOmy9/F6T yL2K/dH14ckHhJEhkrt/H9Gjk7lDLWzmPoGMVzDHA1B67gsuKOkkJsaVUsZkIcsP3NNC qXWZV+O6wu0v1e8sgfAS5Qj561lgUOWIW07IShoyFg3Icl66p/bhYr1QckTQ9qNh11X6 V8ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=/KKi9MlyC2ajPTEhQDnm5E6c9PeX2Yx/QSrAgq67sV0=; b=uR2IzGCPHqW360yQLygRt5mSF+FAZ5jgRMTx5dT5LvTbn5ewaYGQ1++mujH4wELc4+ wpbkz19EgxeXWtxsjWM0iaQAkNAZX+4uPKP8E970wwQnUGdeg8uYS7gP7SoNvS3Pa5Uk tF3nLYvR1hrwGpSTay+p/K7AOaOJ1nxUWsmHXsZXISj8/Ju1+ZhwUKvlV9cDIJ5UK2IH MJjT2IKXELVQ+xdTA9KJD7qA+fa6uXJ8Lc5i37Ag8vZ/4dqpy9rcrOhjPSYwZDgZJWR5 J67O/XfxXDcKNlatQa+pnHDbfu4E74xfw4IZqYOtu5Vdk9fXb5Q+KMtXj9DvaiuEZoIW paWg== X-Gm-Message-State: AOAM5315zaq98v84H6tSaUUoVp5P0xqvWKY0h4TjPVYFTULrqD3fTg/3 dUbb4Jm9KGJOl+5yYP9mFEVV9HhACG8b16Y7+JLIhaZG X-Google-Smtp-Source: ABdhPJwJrF7Gh0KruLiHcHkvE8ooPLs9uzmqFST2tzOE8V+NFPH4+gUgYCeDHM4cTALclsYAz0BWVOuLDhvTORrZU+U= X-Received: by 2002:a2e:7114:: with SMTP id m20mr19542957ljc.229.1636770733678; Fri, 12 Nov 2021 18:32:13 -0800 (PST) MIME-Version: 1.0 From: Steve French Date: Fri, 12 Nov 2021 20:32:02 -0600 Message-ID: Subject: updated Linux client multichannel patches To: Shyam Prasad N , CIFS Cc: Paulo Alcantara Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org I updated patch 3 of Shyam's multichannel series to fix merge conflicts with Paulo's earlier DFS patches. See attached. Tentatively have merged the following 4 into for-next pending more testing. From 0f2b305af944973d6fa4acdb97151efe5b64aa55 Mon Sep 17 00:00:00 2001 From: Shyam Prasad N Date: Mon, 19 Jul 2021 11:26:24 +0000 Subject: [PATCH 3/4] cifs: connect individual channel servers to primary channel server Today, we don't have any way to get the smb session for any of the secondary channels. Introducing a pointer to the primary server from server struct of any secondary channel. The value will be NULL for the server of the primary channel. This will enable us to get the smb session for any channel. This will be needed for some of the changes that I'm planning to make soon. Signed-off-by: Shyam Prasad N Signed-off-by: Steve French --- fs/cifs/cifs_debug.c | 3 ++- fs/cifs/cifsglob.h | 10 +++++++++- fs/cifs/cifsproto.h | 5 +++-- fs/cifs/connect.c | 24 ++++++++++++++++++++---- fs/cifs/sess.c | 6 +----- fs/cifs/smb2pdu.c | 2 +- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 248a8f973cf9..d282caf9f037 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -271,7 +271,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) c = 0; spin_lock(&cifs_tcp_ses_lock); list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { - if (server->is_channel) + /* channel info will be printed as a part of sessions below */ + if (CIFS_SERVER_IS_CHAN(server)) continue; c++; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 3c18c56a119b..be74606724c7 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -690,7 +690,15 @@ struct TCP_Server_Info { */ int nr_targets; bool noblockcnt; /* use non-blocking connect() */ - bool is_channel; /* if a session channel */ + + /* + * If this is a session channel, + * primary_server holds the ref-counted + * pointer to primary channel connection for the session. + */ +#define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server) + struct TCP_Server_Info *primary_server; + #ifdef CONFIG_CIFS_SWN_UPCALL bool use_swn_dstaddr; struct sockaddr_storage swn_dstaddr; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b2697356b5e7..f3073a62ce57 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -269,8 +269,9 @@ extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon); extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, const char *path); - -extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx); +extern struct TCP_Server_Info * +cifs_get_tcp_session(struct smb3_fs_context *ctx, + struct TCP_Server_Info *primary_server); extern void cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect); extern void cifs_put_tcon(struct cifs_tcon *tcon); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 09a532ed8fe4..f80b73f2d0a0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -173,6 +173,7 @@ static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server struct cifs_tcon *tcon; struct mid_q_entry *mid, *nmid; struct list_head retry_list; + struct TCP_Server_Info *pserver; server->maxBuf = 0; server->max_read = 0; @@ -184,8 +185,12 @@ static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server * are not used until reconnected. */ cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", __func__); + + /* If server is a channel, select the primary channel */ + pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; + spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { ses->need_reconnect = true; list_for_each_entry(tcon, &ses->tcon_list, tcon_list) tcon->need_reconnect = true; @@ -1338,7 +1343,7 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx) * Skip ses channels since they're only handled in lower layers * (e.g. cifs_send_recv). */ - if (server->is_channel || !match_server(server, ctx)) + if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) continue; ++server->srv_count; @@ -1369,6 +1374,10 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) list_del_init(&server->tcp_ses_list); spin_unlock(&cifs_tcp_ses_lock); + /* For secondary channels, we pick up ref-count on the primary server */ + if (CIFS_SERVER_IS_CHAN(server)) + cifs_put_tcp_session(server->primary_server, from_reconnect); + cancel_delayed_work_sync(&server->echo); cancel_delayed_work_sync(&server->resolve); @@ -1401,7 +1410,8 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) } struct TCP_Server_Info * -cifs_get_tcp_session(struct smb3_fs_context *ctx) +cifs_get_tcp_session(struct smb3_fs_context *ctx, + struct TCP_Server_Info *primary_server) { struct TCP_Server_Info *tcp_ses = NULL; int rc; @@ -1438,6 +1448,10 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx) tcp_ses->in_flight = 0; tcp_ses->max_in_flight = 0; tcp_ses->credits = 1; + if (primary_server) { + ++primary_server->srv_count; + tcp_ses->primary_server = primary_server; + } init_waitqueue_head(&tcp_ses->response_q); init_waitqueue_head(&tcp_ses->request_q); INIT_LIST_HEAD(&tcp_ses->pending_mid_q); @@ -1559,6 +1573,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx) out_err: if (tcp_ses) { + if (CIFS_SERVER_IS_CHAN(tcp_ses)) + cifs_put_tcp_session(tcp_ses->primary_server, false); kfree(tcp_ses->hostname); if (tcp_ses->ssocket) sock_release(tcp_ses->ssocket); @@ -2960,7 +2976,7 @@ static int mount_get_conns(struct mount_ctx *mnt_ctx) xid = get_xid(); /* get a reference to a tcp session */ - server = cifs_get_tcp_session(ctx); + server = cifs_get_tcp_session(ctx, NULL); if (IS_ERR(server)) { rc = PTR_ERR(server); server = NULL; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 27660bffb918..2c10b186ed6e 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -258,7 +258,7 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, SMB2_CLIENT_GUID_SIZE); ctx.use_client_guid = true; - chan_server = cifs_get_tcp_session(&ctx); + chan_server = cifs_get_tcp_session(&ctx, ses->server); mutex_lock(&ses->session_mutex); spin_lock(&ses->chan_lock); @@ -272,10 +272,6 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, } spin_unlock(&ses->chan_lock); - spin_lock(&cifs_tcp_ses_lock); - chan->server->is_channel = true; - spin_unlock(&cifs_tcp_ses_lock); - /* * We need to allocate the server crypto now as we will need * to sign packets before we generate the channel signing key diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 5e032b2b2adb..2f5f2c4c6183 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -257,7 +257,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, /* * If we are reconnecting an extra channel, bind */ - if (server->is_channel) { + if (CIFS_SERVER_IS_CHAN(server)) { ses->binding = true; ses->binding_chan = cifs_ses_find_chan(ses, server); } -- 2.32.0