Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2230156/?format=api
{ "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" ] }