get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2230156/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2230156,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2230156/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260429121013.1696901-1-charsyam@gmail.com/",
    "project": {
        "id": 12,
        "url": "http://patchwork.ozlabs.org/api/1.1/projects/12/?format=api",
        "name": "Linux CIFS Client",
        "link_name": "linux-cifs-client",
        "list_id": "linux-cifs.vger.kernel.org",
        "list_email": "linux-cifs@vger.kernel.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20260429121013.1696901-1-charsyam@gmail.com>",
    "date": "2026-04-29T12:10:13",
    "name": "[v4] smb: client: fix state-consistency bugs in smb3_reconfigure() multichannel path",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "fb61c0b7413c42316e2235c4dd4b7794289c5f18",
    "submitter": {
        "id": 93166,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/93166/?format=api",
        "name": "DaeMyung Kang",
        "email": "charsyam@gmail.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260429121013.1696901-1-charsyam@gmail.com/mbox/",
    "series": [
        {
            "id": 502043,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/502043/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=502043",
            "date": "2026-04-29T12:10:13",
            "name": "[v4] smb: client: fix state-consistency bugs in smb3_reconfigure() multichannel path",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/502043/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2230156/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2230156/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <linux-cifs+bounces-11273-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-cifs@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=sPkLAcM8;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c15:e001:75::12fc:5321; helo=sin.lore.kernel.org;\n envelope-from=linux-cifs+bounces-11273-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"sPkLAcM8\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.214.173",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com"
        ],
        "Received": [
            "from sin.lore.kernel.org (sin.lore.kernel.org\n [IPv6:2600:3c15:e001:75::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g5GNV39ltz1yHX\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 22:10:50 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sin.lore.kernel.org (Postfix) with ESMTP id AB42B30074C1\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 12:10:23 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 4C88D3F789A;\n\tWed, 29 Apr 2026 12:10:23 +0000 (UTC)",
            "from mail-pl1-f173.google.com (mail-pl1-f173.google.com\n [209.85.214.173])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id D6A4A3F7878\n\tfor <linux-cifs@vger.kernel.org>; Wed, 29 Apr 2026 12:10:19 +0000 (UTC)",
            "by mail-pl1-f173.google.com with SMTP id\n d9443c01a7336-2a8720818aeso11911665ad.1\n        for <linux-cifs@vger.kernel.org>;\n Wed, 29 Apr 2026 05:10:19 -0700 (PDT)",
            "from ser8.. ([221.156.231.192])\n        by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b988772c33sm21595265ad.8.2026.04.29.05.10.16\n        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n        Wed, 29 Apr 2026 05:10:18 -0700 (PDT)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777464622; cv=none;\n b=S1osnB43jpibYO2ZfAyO5j3oJze+pVerAMudeEzOU4+07SrBFaY6HPQEEhaVgde3WUIAiVbp6DhLpVYnjaQe0srMOMnaVLt/BaD5i3McpPuWkdCsiBOSAHWmaIUQQBeJNnEpjSCXevAdkBiuK0x4sAQkIWFMRLaCICVKBt9e7t0=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777464622; c=relaxed/simple;\n\tbh=cCTTWEhsf0bQ84BK4BXa9bK1yg6tDcfHODTee0k3Vgc=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=VOEF5pupz0FzAzJvCZYr+W5ADXiG27fXL6Tf3pJftQjwEovp4P0rI8XsuGFu7JNjzqcilMrN/eSdzegHewJgUjyA08VagjB0j7tbNPRoC4OlltdZO3wt3BGytKebScpeuP6vaEEgdt3H2RJ7C0GkRybAifwhxTCs/Lgc+BNWej8=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=sPkLAcM8; arc=none smtp.client-ip=209.85.214.173",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=gmail.com; s=20251104; t=1777464619; x=1778069419;\n darn=vger.kernel.org;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n         :message-id:reply-to;\n        bh=AfWt2gVjlusGfjLLhXnNRBjdizd4kWhg9rEa/1+nqIQ=;\n        b=sPkLAcM8Yu3B2vVC00Ab3Q6u8r2An0Rp/4NoWje+SdmIfXIap06sBS2Lt6ff3pwCvx\n         CZlvSPvMi+IRI15t0IdBpe+Y790yZ1+Sfr5C7WP8/SYnZfrfgee9Q2fj0+E9YroTepV6\n         ACR3/RyVWXIPImp5T+CoVwtncJ2tRNoIBQu1caKkmWmw73kjwbp1Bzk5mGpest5udKKF\n         FUZ3b2Z98O+/G8O5XhTKqFq/eGyusoMWLBKGVhkMSS5Nec6+bUbBm26ogzMss1e6ZYRW\n         XL8DYjLk9uGODyZfdyipx4nBdCfuAG6/poeVIm7Pn8TCsOl+jv6E4ammKViYm0jDpA8l\n         Ip5w==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=1e100.net; s=20251104; t=1777464619; x=1778069419;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n         :to:cc:subject:date:message-id:reply-to;\n        bh=AfWt2gVjlusGfjLLhXnNRBjdizd4kWhg9rEa/1+nqIQ=;\n        b=Vz9X8YuOslCObhIlICWJAU4Adk2BPuEpWrE9d+5WqkE5RDg2YWoecgccs10qiyHn7y\n         mGnLE0gJpZqXhZ1qrZbwIQHz9vl0raZRqpkv55vbvjtaTfZKYMo7s8UxyTdSnUrbXiq5\n         STg2rOIQ32N6bLy9PCH8VkVEFgSb83JF9g/4BS22MA/Ko/AUVONEV8ZU7y1j8Nq/KfSe\n         DJnjk9f84Fu89N38FuTfPb4sHVDrVSCsKiTlxBKX6AUmYh9TOIiTHvODYDpb7I8bm/2/\n         weV7ZXazHHTqNLwDM1VKko41/HtpjcbRRVm9lD4SMpbOnAT2pryMd6Qw6h4hyxjlh/xS\n         /8yA==",
        "X-Forwarded-Encrypted": "i=1;\n AFNElJ+MYUk1bzzMv8p9osC7qycIqaZXUbHsZbK7HsqNrSEg69BiRnCbN7dmnavqhWj4HhdLUjKI2lv7F6y9@vger.kernel.org",
        "X-Gm-Message-State": "AOJu0YzZXyv4WD5XGA+UJwBEMdl6l99nt/sSoTS93mMFKcojV2G9XQVn\n\t5KPNzoH2HYf5vhXSpPLwBLCUfdL9AVU/krA4yt+K23awAg1tHTow7tUm",
        "X-Gm-Gg": "AeBDieu88s7C9BOQWVG8eATeCCSHfcI1/wVlWHd4FENstMGQhXVgLv6XjvuXQbjo6Mt\n\tKtu3q+d4pmKUtB/hoiMwhryP/VbhcvHl6rPcvhq45DaJIJMghFtioK+zuGBnGrCDkoON1AnBQvb\n\tN71bptqzn0tEVlCavq2bG83CLsNxUEpGSa8Rwnb211Ug8dusPTVhP5O+LVqgq1veyrQjkSsOqzi\n\tO8c+9+yR4Fm24pac0SxHq40C9mNH4kJpiC10MVE/Wsc/LP/wJ5sHW2ngPVLggAdQsbte5wzCpJC\n\t4ReqZM23/Abn+S92Y/2kBGbrDJtoWnL1+FJlpWgacW+Hv8a14ngt/bIxY8MKvnzmBaCOwv9jGc+\n\tpP7Kll5K2PZOOzAt9JO5zdAJmKNWomDRcPlCfajTTXRWrZIeoXtrK8rqKceraYmITrnvkR/yrLn\n\tRt6L9ud87zZ7f7qLQLuP6tN4Ca5ek=",
        "X-Received": "by 2002:a17:903:3e0a:b0:2ae:7edc:9234 with SMTP id\n d9443c01a7336-2b97a7985c3mr26633445ad.1.1777464618855;\n        Wed, 29 Apr 2026 05:10:18 -0700 (PDT)",
        "From": "DaeMyung Kang <charsyam@gmail.com>",
        "To": "Steve French <sfrench@samba.org>,\n\tPaulo Alcantara <pc@manguebit.org>",
        "Cc": "Ronnie Sahlberg <ronniesahlberg@gmail.com>,\n\tShyam Prasad N <sprasad@microsoft.com>,\n\tTom Talpey <tom@talpey.com>,\n\tBharath SM <bharathsm@microsoft.com>,\n\tRajasi Mandal <rajasimandal@microsoft.com>,\n\tRajasi Mandal <rajasimandalos@gmail.com>,\n\tlinux-cifs@vger.kernel.org,\n\tsamba-technical@lists.samba.org,\n\tlinux-kernel@vger.kernel.org,\n\tDaeMyung Kang <charsyam@gmail.com>",
        "Subject": "[PATCH v4] smb: client: fix state-consistency bugs in\n smb3_reconfigure() multichannel path",
        "Date": "Wed, 29 Apr 2026 21:10:13 +0900",
        "Message-ID": "<20260429121013.1696901-1-charsyam@gmail.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20260416151839.3315696-1-charsyam@gmail.com>",
        "References": "<20260416151839.3315696-1-charsyam@gmail.com>",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-cifs@vger.kernel.org",
        "List-Id": "<linux-cifs.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-cifs+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-cifs+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit"
    },
    "content": "smb3_reconfigure() has several state-consistency bugs when handling\na multichannel remount that leave ses->chan_max or cifs_sb->ctx\ninconsistent with the actual state. This patch repairs internal\nstate only; the userspace-visible return value of\nsmb3_reconfigure() is preserved to match the pre-patch behaviour:\nthe concurrent-scale loser path still returns -EINVAL, and a\nfailed smb3_update_ses_channels() is not newly propagated to\nuserspace by this patch.\n\nBugs addressed:\n\n1) Before this patch, smb3_sync_ses_chan_max() is called before\n   acquiring CIFS_SES_FLAG_SCALE_CHANNELS. If a concurrent\n   operation (e.g. smb2_reconnect) holds the flag, the current\n   thread takes the loser path and returns -EINVAL, but\n   ses->chan_max has already been updated to the new value.\n   chan_max is then out of sync with the actual channel state.\n\n2) When smb3_update_ses_channels() fails, ses->chan_max is not\n   rolled back. Repeated failures cause chan_max to drift further\n   from reality, and subsequent reconnect/reconfigure paths use\n   the drifted target.\n\n3) Earlier in smb3_reconfigure(), STEAL_STRING moves UNC, source\n   and username from cifs_sb->ctx into ctx, setting\n   cifs_sb->ctx->UNC to NULL until smb3_fs_context_dup() copies\n   them back near the end of the function. The pre-existing\n   CIFS_SES_FLAG_SCALE_CHANNELS loser-path 'return -EINVAL' exits\n   inside this window. A loser-path failure therefore permanently\n   nulls cifs_sb->ctx->UNC; /proc/mounts shows the device as\n   \"none\" and every subsequent mount.cifs-based remount is\n   rejected by smb3_verify_reconfigure_ctx() because mount.cifs\n   passes that \"none\" back as the new UNC.\n\n4) Once (2) rolls ses->chan_max back to the old value on update\n   failure, smb3_fs_context_dup() would still copy the rejected\n   new ctx->max_channels into cifs_sb->ctx, creating a fresh\n   cifs_sb->ctx vs ses->chan_max mismatch. This must be handled\n   together with (2) to keep the rollback complete.\n\nFix all four by:\n\n - Moving smb3_sync_ses_chan_max() after the SCALE_CHANNELS\n   acquire so the loser path cannot corrupt chan_max.\n\n - Capturing old_chan_max atomically with the sync via the new\n   smb3_sync_ses_chan_max() return value (under chan_lock), and\n   restoring it on failure while still holding SCALE_CHANNELS so\n   a concurrent reconfigure cannot race with the rollback.\n\n - Recording any multichannel-path failure in a local mchan_rc\n   and routing the loser path through a common 'out:' label so\n   every exit reaches smb3_fs_context_dup() and cifs_sb->ctx is\n   restored. mchan_rc is used only as internal control flow.\n\n - Before the dup, restoring ctx->multichannel,\n   ctx->multichannel_specified, ctx->max_channels and\n   ctx->max_channels_specified from cifs_sb->ctx on mchan_rc so\n   the dup does not desync cifs_sb->ctx from the already-rolled-\n   back ses->chan_max (the *_specified bits must travel with the\n   values to avoid a \"user-specified\" flag mismatching the\n   restored value).\n\n - Tracking the concurrent-scale loser path with a separate\n   scale_busy flag. After cifs_sb->ctx is fully restored, the\n   return value is forced to -EINVAL for that path so userspace\n   continues to see the pre-patch rejection. dup /\n   dfs_cache_remount_fs() failures still take precedence because\n   they reflect real state recovery errors.\n\nDeliberately not changed by this patch: the return value of\nsmb3_reconfigure() on smb3_update_ses_channels() failure. That\npath is not newly propagated to userspace here, matching the\nasynchronous model used by the mount path (mchan_mount_work_fn).\nThose return-semantics and deferred-handling questions are left\nto follow-up discussion/patches.\n\nsmb3_reconfigure() is not fully transactional: ses->password and\nses->password2 are committed before the multichannel block, so\nunrelated earlier state changes may still be visible after a\nfailed multichannel remount. That is a structural property of\nthe function and out of scope here.\n\nTested with a QEMU VM (ksmbd + cifs) using module-parameter\nbased fault injection:\n - Forced smb3_update_ses_channels() failure via module param\n   and verified ses->chan_max is preserved at the old value\n   after the remount path runs.\n - Pre-set CIFS_SES_FLAG_SCALE_CHANNELS before entering the\n   scaling path and verified the loser path still returns\n   -EINVAL, no longer corrupts ses->chan_max, and no longer nulls\n   cifs_sb->ctx->UNC.\n - Repeated dozens of forced-failure remounts with varying\n   max_channels (range 2-8) and confirmed no chan_max drift.\n - After each failure path, verified /proc/mounts continues to\n   show the original UNC (//127.0.0.1/share) so subsequent\n   remounts are accepted.\n\nReported-by: RAJASI MANDAL <rajasimandalos@gmail.com>\nCloses: https://lore.kernel.org/lkml/CAEY6_V1+dzW3OD5zqXhsWyXwrDTrg5tAMGZ1AJ7_GAuRE+aevA@mail.gmail.com/\nLink: https://lore.kernel.org/lkml/xkr2dlvgibq5j6gkcxd3yhhnj4atgxw2uy4eug2pxm7wy7nbms@iq6cf5taa65v/\nFixes: ef529f655a2c (\"cifs: client: allow changing multichannel mount options on remount\")\nSigned-off-by: DaeMyung Kang <charsyam@gmail.com>\n---\nv4: (feedback from Rajasi Mandal)\n - Fix unlocked read of ses->chan_max when capturing the rollback\n   value. smb3_sync_ses_chan_max() now returns the previous\n   chan_max so the read+write happens atomically under chan_lock,\n   removing the data race against cifs_try_adding_channels() /\n   cifs_chan_skip_or_disable() which also access chan_max under\n   chan_lock.\n - Switch smb3_sync_ses_chan_max()'s parameter/return type to\n   size_t to match struct cifs_ses::chan_max.\n - On the multichannel rollback path, also restore\n   ctx->multichannel_specified and ctx->max_channels_specified\n   from cifs_sb->ctx so the user-specified flags do not desync\n   from the restored values when smb3_fs_context_dup() copies\n   ctx back.\n\nv3: (feedback from Henrique Carvalho)\n - Drop propagation of smb3_update_ses_channels() failure to\n   userspace; preserve the pre-patch best-effort semantics on that\n   path.\n - Keep the pre-existing CIFS_SES_FLAG_SCALE_CHANNELS loser-path\n   -EINVAL via a separate scale_busy flag so that return is not\n   silently converted into success.\n - Reword commit message to describe accurately what userspace-\n   visible semantics are preserved and what changed internally.\n\nv2: (feedback from Rajasi Mandal)\n - Route loser-path and update-failure exits through a common\n   'out:' label so smb3_fs_context_dup() always runs and\n   cifs_sb->ctx->UNC is restored after STEAL_STRING.\n - Restore ctx->multichannel/ctx->max_channels from cifs_sb->ctx\n   before the dup so dup does not re-desync cifs_sb->ctx from the\n   rolled-back ses->chan_max.\n\n fs/smb/client/fs_context.c | 61 +++++++++++++++++++++++++++++++++++---------\n 1 file changed, 52 insertions(+), 9 deletions(-)\n\n--\n2.43.0",
    "diff": "diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c\nindex b9544eb0381b..252420bd7d5d 100644\n--- a/fs/smb/client/fs_context.c\n+++ b/fs/smb/client/fs_context.c\n@@ -767,7 +767,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,\n static int smb3_fs_context_parse_monolithic(struct fs_context *fc,\n \t\t\t\t\t    void *data);\n static int smb3_get_tree(struct fs_context *fc);\n-static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channels);\n+static size_t smb3_sync_ses_chan_max(struct cifs_ses *ses, size_t max_channels);\n static int smb3_reconfigure(struct fs_context *fc);\n\n static const struct fs_context_operations smb3_fs_context_ops = {\n@@ -1069,14 +1069,20 @@ int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_se\n  * @max_channels: new maximum number of channels to allow\n  *\n  * Updates the session's chan_max field to the new value, protecting the update\n- * with the session's channel lock. This should be called whenever the maximum\n- * allowed channels for a session changes (e.g., after a remount or reconfigure).\n+ * with the session's channel lock, and returns the previous chan_max value.\n+ * This should be called whenever the maximum allowed channels for a session\n+ * changes (e.g., after a remount or reconfigure).\n  */\n-static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channels)\n+static size_t smb3_sync_ses_chan_max(struct cifs_ses *ses, size_t max_channels)\n {\n+\tsize_t old_chan_max;\n+\n \tspin_lock(&ses->chan_lock);\n+\told_chan_max = ses->chan_max;\n \tses->chan_max = max_channels;\n \tspin_unlock(&ses->chan_lock);\n+\n+\treturn old_chan_max;\n }\n\n static int smb3_reconfigure(struct fs_context *fc)\n@@ -1085,10 +1091,12 @@ static int smb3_reconfigure(struct fs_context *fc)\n \tstruct dentry *root = fc->root;\n \tstruct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);\n \tstruct cifs_ses *ses = cifs_sb_master_tcon(cifs_sb)->ses;\n+\tsize_t old_chan_max;\n \tunsigned int rsize = ctx->rsize, wsize = ctx->wsize;\n \tchar *new_password = NULL, *new_password2 = NULL;\n \tbool need_recon = false;\n-\tint rc;\n+\tbool scale_busy = false;\n+\tint rc, mchan_rc = 0;\n\n \tif (ses->expired_pwd)\n \t\tneed_recon = true;\n@@ -1170,25 +1178,37 @@ static int smb3_reconfigure(struct fs_context *fc)\n \tif ((ctx->multichannel != cifs_sb->ctx->multichannel) ||\n \t    (ctx->max_channels != cifs_sb->ctx->max_channels)) {\n\n-\t\t/* Synchronize ses->chan_max with the new mount context */\n-\t\tsmb3_sync_ses_chan_max(ses, ctx->max_channels);\n-\t\t/* Now update the session's channels to match the new configuration */\n \t\t/* Prevent concurrent scaling operations */\n \t\tspin_lock(&ses->ses_lock);\n \t\tif (ses->flags & CIFS_SES_FLAG_SCALE_CHANNELS) {\n \t\t\tspin_unlock(&ses->ses_lock);\n \t\t\tmutex_unlock(&ses->session_mutex);\n-\t\t\treturn -EINVAL;\n+\t\t\tscale_busy = true;\n+\t\t\tmchan_rc = -EINVAL;\n+\t\t\tgoto out;\n \t\t}\n \t\tses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS;\n \t\tspin_unlock(&ses->ses_lock);\n\n+\t\t/* Synchronize ses->chan_max with the new mount context */\n+\t\told_chan_max = smb3_sync_ses_chan_max(ses, ctx->max_channels);\n+\n \t\tmutex_unlock(&ses->session_mutex);\n\n \t\trc = smb3_update_ses_channels(ses, ses->server,\n \t\t\t\t\t       false /* from_reconnect */,\n \t\t\t\t\t       false /* disable_mchan */);\n\n+\t\t/*\n+\t\t * On failure, restore chan_max while still holding\n+\t\t * CIFS_SES_FLAG_SCALE_CHANNELS so a concurrent reconfigure\n+\t\t * cannot observe or race with the rollback.\n+\t\t */\n+\t\tif (rc < 0) {\n+\t\t\tsmb3_sync_ses_chan_max(ses, old_chan_max);\n+\t\t\tmchan_rc = rc;\n+\t\t}\n+\n \t\t/* Clear scaling flag after operation */\n \t\tspin_lock(&ses->ses_lock);\n \t\tses->flags &= ~CIFS_SES_FLAG_SCALE_CHANNELS;\n@@ -1197,6 +1217,7 @@ static int smb3_reconfigure(struct fs_context *fc)\n \t\tmutex_unlock(&ses->session_mutex);\n \t}\n\n+out:\n \tSTEAL_STRING(cifs_sb, ctx, domainname);\n \tSTEAL_STRING(cifs_sb, ctx, nodename);\n \tSTEAL_STRING(cifs_sb, ctx, iocharset);\n@@ -1205,6 +1226,18 @@ static int smb3_reconfigure(struct fs_context *fc)\n \tctx->rsize = rsize ? CIFS_ALIGN_RSIZE(fc, rsize) : cifs_sb->ctx->rsize;\n \tctx->wsize = wsize ? CIFS_ALIGN_WSIZE(fc, wsize) : cifs_sb->ctx->wsize;\n\n+\t/*\n+\t * If the multichannel update failed, restore the old multichannel\n+\t * settings in ctx so smb3_fs_context_dup() does not desync\n+\t * cifs_sb->ctx from ses->chan_max (which was already rolled back).\n+\t */\n+\tif (mchan_rc) {\n+\t\tctx->multichannel = cifs_sb->ctx->multichannel;\n+\t\tctx->multichannel_specified = cifs_sb->ctx->multichannel_specified;\n+\t\tctx->max_channels = cifs_sb->ctx->max_channels;\n+\t\tctx->max_channels_specified = cifs_sb->ctx->max_channels_specified;\n+\t}\n+\n \tsmb3_cleanup_fs_context_contents(cifs_sb->ctx);\n \trc = smb3_fs_context_dup(cifs_sb->ctx, ctx);\n \tsmb3_update_mnt_flags(cifs_sb);\n@@ -1213,6 +1246,16 @@ static int smb3_reconfigure(struct fs_context *fc)\n \t\trc = dfs_cache_remount_fs(cifs_sb);\n #endif\n\n+\t/*\n+\t * Preserve the pre-existing loser-path semantics: a concurrent\n+\t * scaling operation causes the remount to be rejected with\n+\t * -EINVAL. smb3_fs_context_dup() / dfs_cache_remount_fs()\n+\t * failures take precedence because they reflect real state\n+\t * recovery errors. Other multichannel failures remain best-effort.\n+\t */\n+\tif (!rc && scale_busy)\n+\t\trc = -EINVAL;\n+\n \treturn rc;\n }\n\n",
    "prefixes": [
        "v4"
    ]
}