From nobody Tue Dec 2 02:20:18 2025 Received: from mail-il1-f226.google.com (mail-il1-f226.google.com [209.85.166.226]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BDC662989BF for ; Wed, 19 Nov 2025 19:19:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763579948; cv=none; b=FDcRv/cgkDqxO5/yqMANeg48//OZ6Rgv80bfVrSs6uCNYf8UQFvlDpeV8ug1JD3LgirYcKGxEnb98wkO3xelcuh6hu/MfUeTKPRQrYeBEvHXI0wLbijDsc+x63rsdkil0r3OpSm58ar3EnwC9oru5q17guC7Xj4moCf0Q9GrUDE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763579948; c=relaxed/simple; bh=kVzolTlCZ2Po5R+C/d29DI9nx0YjDbRrv8IvXwszvJQ=; h=From:To:Cc:Subject:Date:Message-ID; b=TEALgoJ1QH64CVm59c4jJDdkuld56n2OYFegikgDn23/QAYvdeZwI/twQSu+aM9mjSKNmwY51TEkeKmEwXKCYX6SYIsh6jJKaWBr7gZA5boZHg7RoIWRYkSjRoYOWrqeVhsYvu8CbYLuL+U7Q/DycrQHTBManBVJXpkqqWrWZQg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=arista.com; spf=pass smtp.mailfrom=arista.com; dkim=pass (2048-bit key) header.d=arista.com header.i=@arista.com header.b=TgrtLiS1; arc=none smtp.client-ip=209.85.166.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=arista.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arista.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=arista.com header.i=@arista.com header.b="TgrtLiS1" Received: by mail-il1-f226.google.com with SMTP id e9e14a558f8ab-43376624a8fso847125ab.0 for ; Wed, 19 Nov 2025 11:19:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763579935; x=1764184735; h=content-transfer-encoding:message-id:date:subject:cc:to:from :dkim-signature:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=YofaLi3MesTvIuKNFgHZMO8FPT98w0mEGlDeeF1DoxM=; b=hLjFKJyo0gO6l+I2RdYZtejEZe0wasdtqUv+GyPvR6DySnjBc+JCGOU3zNgqOxSXm3 v3DJzJrm51FUVLqhhKxnPOMsQNSsQN4CPz/kGRXDsziCrCwHVpk4Rq+6lMGQGLkjsaVu +W9w+T57Evk6+hH1Ixwyu7REGzm6U2HWfYA4/vlT0WS95F7oAV98kv8BRRQp73C6o/8D MJ5I9DfddTg8d8+P1ILRHMZlad+6ZZhC2UiDijcser9ces0qNuiD91KqkVQf26Fxt2vD 7gkLCtfXH5sAT1qkgwXdGQ/9smSU3MIG4P54eEFpC887qMc6ffklqw2xe0xXxL3X6Zme Z/NA== X-Forwarded-Encrypted: i=1; AJvYcCXxoKFtMOpSYGRTaPYWRYgXvpLHfCUVuxUa5FTU0s4kUlxGDdfdRMCUl83wdPTlCmKoBKctMPLm9QDeN30=@vger.kernel.org X-Gm-Message-State: AOJu0YzvE9AeG7yhFxLt9BIXPWfs22jL2rdRmTr/281kdtLtHnnNHTyf otjzUIZ1l92yUH2BCR2Phl7F4h34RfH2bM8GcGYuUsHvbzRM3uheP3M5so6Kttcp359/65Q4Qw0 yWGK8BrcFnU+pVBauOkmYuUmpMNCnNPkM3w== X-Gm-Gg: ASbGncuvl7YN8ENHnqerSgUrxuOC3atG7iWSsEhTvBZxqXhmJhsvBbiUb1VEai4brk0 eNwPMOoRSTfMNauglBlTBtM5nIH99OdKceCUATJPIE7/kgMimkrqieTpj1wpBEckLdrIUZDD6zd SxhyRcr7dnPQ6jP8qsbtiNtbojb6z+aUvu2k7xM/v8EbzBzToK6gcV6iAtUpB//CtVznUmvwvvR o4cobcZltR5G/ZZJMaPGzxEvV+kzJ5pMAK/UlJQ5qv68Ch4VXcCY4WrCFVC4r551zvjdGCKq4Ec rWx5s03DEwIGwZX9MBCdur2NoNQuwe6YEeKerxisKTNP558Awh0PTxX2EiyuCBUNXKKuDCPnpxc oaLTdgKjDHEQAitOzstTFpg== X-Google-Smtp-Source: AGHT+IHk9xZc05aG01QOen6EKaoVAlGOI7rA8G2z2y/2wQmkXIH3YXypNUKz51XgdvkBpRZYd6mODKn/F8p0 X-Received: by 2002:a05:6e02:154d:b0:435:a148:d3c with SMTP id e9e14a558f8ab-435a9092e99mr6192445ab.41.1763579934934; Wed, 19 Nov 2025 11:18:54 -0800 (PST) Received: from smtp.aristanetworks.com ([74.123.28.25]) by smtp-relay.gmail.com with ESMTPS id e9e14a558f8ab-435a905e04asm365195ab.9.2025.11.19.11.18.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Nov 2025 11:18:54 -0800 (PST) X-Relaying-Domain: arista.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=Arista-A; t=1763579934; bh=YofaLi3MesTvIuKNFgHZMO8FPT98w0mEGlDeeF1DoxM=; h=From:To:Cc:Subject:Date:From; b=TgrtLiS1Vi96x+2CpSXDXOfs+08kAcuL3WdwHKA1ftEZ15+j2NmiIJKY5eW/73zOV kUYq5Y/e+2rfmalgXybkPTMPxB1ihXiMlK7+oqZXFdTOYb9Fc0q4gIm2swXbIbBwAZ ucqokP5GXkpS7xOkNEd5gNdd/F7HgXpSeNHlONqYZoEnJB/mlVavTN1wDyefKCeb5Z DuH/gLbumkzE1XyAdjBvlL9GMYMmdSk5pyBWCzrOymIZaAVtMqBi87YpHjuibdROt4 7u84aA9CRRdDdLkWtEU6tz1r8zGnZGGgUVjFgmbZ0yBgbwM+uF1C74oq6EFK1trAJG 0PNDlJI0rYZ1w== Received: from kevmitch-g-eos-trunk-kernel6-2.sjc.aristanetworks.com (kevmitch-g-eos-trunk-kernel6-2-us376.sjc.aristanetworks.com [10.247.237.183]) by smtp.aristanetworks.com (Postfix) with ESMTP id 1A34710023B; Wed, 19 Nov 2025 19:18:54 +0000 (UTC) X-SMTP-Authentication: Allow-List-permitted X-SMTP-Authentication: Allow-List-permitted From: Kevin Mitchell To: Tejun Heo Cc: Kevin Mitchell , Greg Kroah-Hartman , Chengming Zhou , linux-kernel@vger.kernel.org Subject: [PATCH] kernfs: use atomics for open_node refcounts Date: Wed, 19 Nov 2025 11:17:57 -0800 Message-ID: <20251119191758.612694-2-kevmitch@arista.com> Content-Transfer-Encoding: quoted-printable Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Counts of files to be released and mmapped files were added to kernfs_open_node in commit bdb2fd7fc56e ("kernfs: Skip kernfs_drain_open_files() more aggressively") to optimize kernfs_drain_open_files(). A WARN_ON_ONCE sanity check was also added in kernfs_drain_open_files to ensure that these counters were brought to zero once all files had been drained. This WARNING was found to trigger on occasion during pci hotplug link down when mmapped pci resource files were removed in pci_remove_resource_files. This was caused by a race condition during the initial mmappings where incrementing nr_mmapped from multiple CPUs such that 2 (or possibly more) simultaneous increments overwrote each other thus appearing as only a single increment. The correct number of kernfs_open_files with mmapped =3D=3D true were nevertheless still present in the kernfs_open_node's files list. Consequently, the iteration in kernfs_drain_open_files would underflow nr_mmapped and the WARNING would fire. Since both nr_mmapped and nr_to_release may be incremented and decremented from multiple CPUs simultaneously without acquiring the kernfs_open_file_mutex_lock, make these members atomic. This should ensure that simultaneous increments and decrements don't overwrite each other. Fixes: bdb2fd7fc56e ("kernfs: Skip kernfs_drain_open_files() more aggressiv= ely") Signed-off-by: Kevin Mitchell --- fs/kernfs/file.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index 9adf36e6364b..a9d0bf82ceba 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -23,8 +23,8 @@ struct kernfs_open_node { atomic_t event; wait_queue_head_t poll; struct list_head files; /* goes through kernfs_open_file.list */ - unsigned int nr_mmapped; - unsigned int nr_to_release; + atomic_t nr_mmapped; + atomic_t nr_to_release; }; =20 /* @@ -503,7 +503,7 @@ static int kernfs_fop_mmap(struct file *file, struct vm= _area_struct *vma) rc =3D 0; if (!of->mmapped) { of->mmapped =3D true; - of_on(of)->nr_mmapped++; + atomic_inc(&of_on(of)->nr_mmapped); of->vm_ops =3D vma->vm_ops; } vma->vm_ops =3D &kernfs_vm_ops; @@ -553,7 +553,7 @@ static int kernfs_get_open_node(struct kernfs_node *kn, =20 list_add_tail(&of->list, &on->files); if (kn->flags & KERNFS_HAS_RELEASE) - on->nr_to_release++; + atomic_inc(&on->nr_to_release); =20 mutex_unlock(mutex); return 0; @@ -592,10 +592,10 @@ static void kernfs_unlink_open_file(struct kernfs_nod= e *kn, if (kn->flags & KERNFS_HAS_RELEASE) { WARN_ON_ONCE(of->released =3D=3D open_failed); if (open_failed) - on->nr_to_release--; + atomic_dec(&on->nr_to_release); } if (of->mmapped) - on->nr_mmapped--; + atomic_dec(&on->nr_mmapped); list_del(&of->list); } =20 @@ -763,7 +763,7 @@ static void kernfs_release_file(struct kernfs_node *kn, */ kn->attr.ops->release(of); of->released =3D true; - of_on(of)->nr_to_release--; + atomic_dec(&of_on(of)->nr_to_release); } } =20 @@ -802,7 +802,8 @@ bool kernfs_should_drain_open_files(struct kernfs_node = *kn) =20 rcu_read_lock(); on =3D rcu_dereference(kn->attr.open); - ret =3D on && (on->nr_mmapped || on->nr_to_release); + ret =3D on && (atomic_read(&on->nr_mmapped) || + atomic_read(&on->nr_to_release)); rcu_read_unlock(); =20 return ret; @@ -827,14 +828,15 @@ void kernfs_drain_open_files(struct kernfs_node *kn) if (of->mmapped) { unmap_mapping_range(inode->i_mapping, 0, 0, 1); of->mmapped =3D false; - on->nr_mmapped--; + atomic_dec(&on->nr_mmapped); } =20 if (kn->flags & KERNFS_HAS_RELEASE) kernfs_release_file(kn, of); } =20 - WARN_ON_ONCE(on->nr_mmapped || on->nr_to_release); + WARN_ON_ONCE(atomic_read(&on->nr_mmapped) || + atomic_read(&on->nr_to_release)); mutex_unlock(mutex); } =20 --=20 2.51.0