{"id":2228104,"url":"http://patchwork.ozlabs.org/api/patches/2228104/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260425093829.4004785-2-charsyam@gmail.com/","project":{"id":12,"url":"http://patchwork.ozlabs.org/api/projects/12/?format=json","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":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260425093829.4004785-2-charsyam@gmail.com>","list_archive_url":null,"date":"2026-04-25T09:38:28","name":"[1/2] ksmbd: rewrite stop_sessions() with restartable iteration","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"26a7598a0241efd70beeefcec8c839fa9df1bcd8","submitter":{"id":93166,"url":"http://patchwork.ozlabs.org/api/people/93166/?format=json","name":"DaeMyung Kang","email":"charsyam@gmail.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260425093829.4004785-2-charsyam@gmail.com/mbox/","series":[{"id":501429,"url":"http://patchwork.ozlabs.org/api/series/501429/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=501429","date":"2026-04-25T09:38:27","name":"ksmbd: fix stop_sessions() iteration and centralize ksmbd_conn release","version":1,"mbox":"http://patchwork.ozlabs.org/series/501429/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2228104/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2228104/checks/","tags":{},"related":[],"headers":{"Return-Path":"\n <linux-cifs+bounces-11107-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=lPGIoVrG;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-cifs+bounces-11107-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=\"lPGIoVrG\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.214.175","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 sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g2lCW424sz1yHv\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 25 Apr 2026 19:39:19 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id EF9C9300C90F\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 25 Apr 2026 09:38:47 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 878DB38B146;\n\tSat, 25 Apr 2026 09:38:47 +0000 (UTC)","from mail-pl1-f175.google.com (mail-pl1-f175.google.com\n [209.85.214.175])\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 1C81B38947C\n\tfor <linux-cifs@vger.kernel.org>; Sat, 25 Apr 2026 09:38:45 +0000 (UTC)","by mail-pl1-f175.google.com with SMTP id\n d9443c01a7336-2b25c84360fso4978225ad.0\n        for <linux-cifs@vger.kernel.org>;\n Sat, 25 Apr 2026 02:38:45 -0700 (PDT)","from ser8.. ([221.156.231.192])\n        by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b606ce9891sm206791725ad.83.2026.04.25.02.38.43\n        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n        Sat, 25 Apr 2026 02:38:44 -0700 (PDT)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777109927; cv=none;\n b=R7V3FGxZZJNocaqa5ZmU3siDs5Hl72utIEECdRA5F1X+zEeG4BG+0QAt8nxO5HHndv9QbXFQcnYd1jvakxVVJ1N001PmU+GJ1jHOpGc5RaFC1FoBiUqWul6yYF4BpWhbH6UJaZmWf3kU7oWkt1P4GX4MerEH3z26NynX2/H/csc=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777109927; c=relaxed/simple;\n\tbh=REzEfWkN6tjWJaQ0H+RiUYIwoU83Xx0WygSxTrhFKbA=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=Oeu9ScPdXEjlnrrLx+w9Ml7ux9ocHBvOkVo4pNB58JystEtuufO14yk0xUPYdmYuFdV92tuVGiwV/EmZV//3MpXMeWZ8BARmwcnHLh1SHdptBIADlMxTmRhFhH02pOxUMtLw1+Nt1kxlUfMTHnmOLSiwpfSF1SWFS78ZIXwIl48=","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=lPGIoVrG; arc=none smtp.client-ip=209.85.214.175","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=gmail.com; s=20251104; t=1777109925; x=1777714725;\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=YB7okcDXB2f9QxPT6JpL0fC68gABv+vXaX5leb6ndF8=;\n        b=lPGIoVrGN7TI1crvVpUmhZ40Qr/CNtZl+2iSetodNgtvJxnDfePjs5n/tqDLq0c9Bc\n         KbRKOOhPUW+mfC/+LhfE1XjYFT1LQK0RVepG6ensH5hMZ+0jSYzKyr1OEpMAEx90lasi\n         L5esQPmMYVDoczahnk5cxX1VEYdDRiqqm3smjPpWxBxQpWb/4RNv6dZzNu8MXF9+q2TZ\n         ++bpqzN44WWwtmLD/VhXrDbmw3uAL2t9I0vYBLL4VDuAf+PAw76RQsmMDUtCXC4SUuEm\n         TK8giTMLD+Cv9Q+NzJkRh/sWz9BeaPAAw8A2mpnTQSdigaksheUq7SgUisaW0IYydyAV\n         PzAg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=1e100.net; s=20251104; t=1777109925; x=1777714725;\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=YB7okcDXB2f9QxPT6JpL0fC68gABv+vXaX5leb6ndF8=;\n        b=YsKd8kjGrdXm8fl6MpTe6mVD4cuzCY1e2tIk8vtewcV2jmf3KrZN3YhXjyakdimYIU\n         UlXFda+UXIqDxH9sEzXdrDNyRL47O8o3YcZgaAwiN9s9FGbNoCI0LU9HXtPw2HSiwKh8\n         yLDn0wVNT5AAFr/tubQOp9J/9DMprOawtjv7EqyZIWYdNs++7GEwQiyh0Ukd7p8lszeZ\n         BcUw69dJdtlPJ5PHhnRvJmntMXRGUldsu2V7D29IWFSbs2ycOznIZgS/5gbT+h+ixY3N\n         5stWv36qqqD/nzoAoi7l7cYDsGhNgdGQhgiXahgs88lr7gBvrZo3IE6gjrwjgGS2Q3h6\n         dM7g==","X-Forwarded-Encrypted":"i=1;\n AFNElJ+uzdDF6es31RZMz/xeaTT++U839iaAXDkcmin50f1egd0kr3S8O4784ikt3LnM0usj/7iShTvw8hTt@vger.kernel.org","X-Gm-Message-State":"AOJu0YxF97UeEg/73PSLd7PiKXUtKhBJkCutUjrkiR12rI+aCG+YzfRE\n\tKK22d/9OvK4mjcmu38n4TBtw4TxCSMQRM9de+LQS8hA0LBwW90vTuqKf","X-Gm-Gg":"AeBDiesFF2QVbITU+ufyPe0nR4xEF9N3yXhBEvPtvL2ndXa7RLCOXgp9km/Aif56Lfk\n\txeVKfRv8ADWP5QJUqQznthpKlPXvRSZsNIEPkObSB72RCEDIG14bCk8aEpZek4YxKz+IYFeZYrj\n\ty2UmRmXIxLUoQHLcGwll7PHSUnva9YXWTIVYrrUIOke3aLd4ReQe23eR0yl8tQT3AbrM7YRi8xn\n\tMohFtiqfNv7JNIMRdIuDyPz09hjESdthJzCVYgQ9SUoz0y8ack2EVonVkiXedPFzzy2XBKo+mgJ\n\tTQQpXwjgQg3SB8GBLsWIW6I4xYb50vIUpTy6Ag5qArxE+ugrhlyR4b0pPpiJbI6GjyAbP+5eM0B\n\tZm0PfcIYI1ILMzFhgH4YHooYfphD3tHte1Qj8I2kBpKmPbn+GNe7oRU+BMPDEJt32OloegheNLz\n\trjPzQIp3TeRe9ffd6o0FnK34FXcT8=","X-Received":"by 2002:a17:903:3b88:b0:2b2:ac6f:104b with SMTP id\n d9443c01a7336-2b5f9e79f5bmr187610395ad.1.1777109925297;\n        Sat, 25 Apr 2026 02:38:45 -0700 (PDT)","From":"DaeMyung Kang <charsyam@gmail.com>","To":"Namjae Jeon <linkinjeon@kernel.org>,\n\tSteve French <smfrench@gmail.com>","Cc":"Sergey Senozhatsky <senozhatsky@chromium.org>,\n\tTom Talpey <tom@talpey.com>,\n\tHyunchul Lee <hyc.lee@gmail.com>,\n\tRonnie Sahlberg <lsahlber@redhat.com>,\n\tlinux-cifs@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tstable@vger.kernel.org,\n\tDaeMyung Kang <charsyam@gmail.com>","Subject":"[PATCH 1/2] ksmbd: rewrite stop_sessions() with restartable iteration","Date":"Sat, 25 Apr 2026 18:38:28 +0900","Message-ID":"<20260425093829.4004785-2-charsyam@gmail.com>","X-Mailer":"git-send-email 2.43.0","In-Reply-To":"<20260425093829.4004785-1-charsyam@gmail.com>","References":"<20260425093829.4004785-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":"stop_sessions() walks conn_list with hash_for_each() and, for every\nentry, drops conn_list_lock across the transport ->shutdown() call\nbefore re-acquiring the read lock to continue the loop.  The hash\nwalk relies on cross-iteration state (the current bucket and the\nhlist position), which is not preserved across unlock/relock: if\nanother thread performs a list mutation during the unlocked window,\nthe ongoing iteration becomes unreliable and can re-visit\nconnections that have already been handled or skip connections that\nhave not.  The outer `if (!hash_empty(conn_list)) goto again;` retry\nmasks the symptom in the common case but does not address the\nunsafe iteration itself.\n\nReframe the loop so it never relies on iterator state across\nunlock/relock.  Under conn_list_lock held for read, pick the first\nconnection whose ->shutdown() has not yet been issued by this path,\npin it by taking an extra reference, record that fact on the\nconnection and mark it EXITING while still inside the locked walk,\nthen drop the lock.  Then call ->shutdown() outside the lock, drop\nthe pin (freeing the connection if the handler already released its\nreference), and restart from the top.\n\nUse a new per-connection flag, conn->stop_called, as the \"shutdown\nissued from stop_sessions()\" marker rather than reusing the status\nstate.  ksmbd_conn_set_exiting() is also invoked by\nksmbd_sessions_deregister() on sibling channels of a multichannel\nsession without issuing a transport shutdown, so treating\nKSMBD_SESS_EXITING as \"already handled here\" would skip connections\nthat still need shutdown() to wake their handler out of recv(),\nleaving the outer retry waiting indefinitely for the hash to drain.\nstop_sessions() is serialised by init_lock in\nksmbd_conn_transport_destroy(), so writing stop_called under the\nread lock has no other writer.\n\nSet EXITING inside the locked walk so the selection, the stop_called\nmarker, and the status transition all happen together, and guard\nagainst regressing a connection that has already advanced to\nKSMBD_SESS_RELEASING on its own (for example, if the handler exited\nits receive loop for an unrelated reason between teardown steps).\n\nWhen the pin drop is the last put, release the transport and pair\nida_destroy(&target->async_ida) with the ida_init() done in\nksmbd_conn_alloc(), so stop_sessions() retiring a connection on its\nown does not leak the xarray backing of the embedded async_ida.\n\nThe outer retry with msleep() is kept to wait for handler threads to\nreach ksmbd_conn_free() and drain the hash.\n\nObserved with an instrumented build that logs one line per visit and\nwidens the unlocked window before ->shutdown() by 200 ms, under\nfive concurrent cifs mounts (nosharesock, one connection each):\n\n  * Current code: the same connection address is revisited many\n    times during a single stop_sessions() call and ->shutdown() is\n    invoked well beyond the number of live connections before the\n    hash finally drains.\n\n  * Rewritten code: each live connection produces exactly one\n    ->shutdown() call; the function returns as soon as the hash is\n    empty.\n\nFunctional teardown via `ksmbd.control --shutdown` with the same\nfive mounts completes cleanly on the rewritten path.\n\nPerformance is observably unchanged.  Tearing down N concurrent\nnosharesock cifs connections with `ksmbd.control --shutdown` +\n`rmmod ksmbd` takes essentially the same wall time before and after\nthe rewrite:\n\n    N        before        after\n    10       4.93s         5.34s\n    30       7.34s         7.03s\n    50       7.31s         7.01s     (3-run avg: 7.04s vs 7.25s)\n   100       6.98s         6.78s\n   200       6.77s         6.89s\n\nand the number of ->shutdown() calls equals the number of live\nconnections on both paths when the race is not widened.  The\nteardown is dominated by the msleep(100)-based outer retry waiting\nfor handler threads to run ksmbd_conn_free(), not by the iteration\nitself; the restartable loop's worst-case O(N^2) visit cost is in\nthe microseconds even at N=200 and sits far below the msleep(100)\ngranularity.\n\nApplied alone on top of ksmbd-for-next-next, this patch does not\nintroduce a new leak site.  Under the same reproducer (10x\nconcurrent-holders + ss -K + ksmbd.control --shutdown + rmmod), the\ntree still shows the pre-existing per-connection transport leak\ncount that arises when the last refcount drop lands in one of\nksmbd_conn_r_count_dec(), __free_opinfo() or session_fd_check() -\nall of which end with a bare kfree() today.  kmemleak backtraces\nfor the unreferenced objects point into the TCP accept path\n(sk_clone -> inet_csk_clone_lock, sock_alloc_inode) and none\ninvolve stop_sessions().  Plugging those bare-kfree sites is the\nresponsibility of the follow-up patch.\n\nFixes: e2f34481b24d (\"cifsd: add server-side procedures for SMB3\")\nCc: stable@vger.kernel.org\nSigned-off-by: DaeMyung Kang <charsyam@gmail.com>\n---\n fs/smb/server/connection.c | 46 +++++++++++++++++++++++++++++++-------\n fs/smb/server/connection.h |  1 +\n 2 files changed, 39 insertions(+), 8 deletions(-)","diff":"diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c\nindex fbbc0529743f..c5aac4946cbe 100644\n--- a/fs/smb/server/connection.c\n+++ b/fs/smb/server/connection.c\n@@ -540,24 +540,54 @@ int ksmbd_conn_transport_init(void)\n \n static void stop_sessions(void)\n {\n-\tstruct ksmbd_conn *conn;\n+\tstruct ksmbd_conn *conn, *target;\n \tstruct ksmbd_transport *t;\n+\tbool any;\n \tint bkt;\n \n+\t/*\n+\t * Serialised via init_lock; no concurrent stop_sessions() can\n+\t * touch conn->stop_called, so writing it under the read lock is\n+\t * safe.\n+\t */\n again:\n+\ttarget = NULL;\n+\tany = false;\n \tdown_read(&conn_list_lock);\n \thash_for_each(conn_list, bkt, conn, hlist) {\n-\t\tt = conn->transport;\n-\t\tksmbd_conn_set_exiting(conn);\n-\t\tif (t->ops->shutdown) {\n-\t\t\tup_read(&conn_list_lock);\n+\t\tany = true;\n+\t\tif (conn->stop_called)\n+\t\t\tcontinue;\n+\t\tatomic_inc(&conn->refcnt);\n+\t\tconn->stop_called = true;\n+\t\t/*\n+\t\t * Mark the connection EXITING while still holding the\n+\t\t * read lock so the selection and the status transition\n+\t\t * happen together.  Do not regress a connection that has\n+\t\t * already advanced to RELEASING on its own (e.g. the\n+\t\t * handler exited its receive loop for an unrelated\n+\t\t * reason).\n+\t\t */\n+\t\tif (READ_ONCE(conn->status) != KSMBD_SESS_RELEASING)\n+\t\t\tksmbd_conn_set_exiting(conn);\n+\t\ttarget = conn;\n+\t\tbreak;\n+\t}\n+\tup_read(&conn_list_lock);\n+\n+\tif (target) {\n+\t\tt = target->transport;\n+\t\tif (t->ops->shutdown)\n \t\t\tt->ops->shutdown(t);\n-\t\t\tdown_read(&conn_list_lock);\n+\t\tif (atomic_dec_and_test(&target->refcnt)) {\n+\t\t\tida_destroy(&target->async_ida);\n+\t\t\tt->ops->free_transport(t);\n+\t\t\tkfree(target);\n \t\t}\n+\t\tgoto again;\n \t}\n-\tup_read(&conn_list_lock);\n \n-\tif (!hash_empty(conn_list)) {\n+\tif (any) {\n \t\tmsleep(100);\n \t\tgoto again;\n \t}\ndiff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h\nindex ae21a1bd4c70..de2d46941c93 100644\n--- a/fs/smb/server/connection.h\n+++ b/fs/smb/server/connection.h\n@@ -49,6 +49,7 @@ struct ksmbd_conn {\n \tstruct mutex\t\t\tsrv_mutex;\n \tint\t\t\t\tstatus;\n \tunsigned int\t\t\tcli_cap;\n+\tbool\t\t\t\tstop_called;\n \tunion {\n \t\t__be32\t\t\tinet_addr;\n #if IS_ENABLED(CONFIG_IPV6)\n","prefixes":["1/2"]}