Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH] IB/cache: Check GID table references before attempting deletion
@ 2026-05-13  8:07 Chenguang Zhao
  2026-05-17 10:32 ` Leon Romanovsky
  0 siblings, 1 reply; 4+ messages in thread
From: Chenguang Zhao @ 2026-05-13  8:07 UTC (permalink / raw)
  To: Jason Gunthorpe, Leon Romanovsky
  Cc: Chenguang Zhao, Kees Cook, Etienne AUJAMES, zhenwei pi,
	Jiri Pirko, Maor Gottlieb, linux-rdma

In the NFS over RDMA environment, repeatedly performing frequent
ifdown/ifup operations on the client may cause df -h to hang.
The kernel log reports an error:
  __ib_cache_gid_add: unable to add gid
  0000:0000:0000:0000:0000:ffff:c0a8:0115 error=-28.
Error code -28 indicates the GID table is full.
The call stack during ifdown is as follows:
  put_gid_entry_locked()
  del_gid()
  _ib_cache_gid_del()
  update_gid()
  update_gid_event_work_handler()

In put_gid_entry_locked(), kref_put(&entry->kref) does not
drop the reference count to zero, so free_gid_entry()
is never invoked to release the entry. Subsequent ifup
attempts keep adding new entries into the GID table,
eventually exhausting the table capacity.

To fix this, check whether the GID entry still has
outstanding references in del_gid(), and only remove
and release the entry when no other references remain.

Signed-off-by: Chenguang Zhao <zhaochenguang@kylinos.cn>
---
 drivers/infiniband/core/cache.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 647a547e2d7f..c71522fbf89f 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -596,6 +596,34 @@ int ib_cache_gid_add(struct ib_device *ib_dev, u32 port,
 	return __ib_cache_gid_add(ib_dev, port, gid, attr, mask, false);
 }
 
+/**
+ * gid_table_is_shared - Check if GID table has other reference owners
+ * @table: GID table to check
+ * @ix: index of entry
+ *
+ * Returns true if the gid table refcount is greater than 1,
+ */
+static bool gid_table_is_shared(struct ib_gid_table *table, int ix)
+{
+	unsigned int refcount;
+	struct ib_gid_table_entry *entry;
+
+	write_lock_irq(&table->rwlock);
+
+	entry = table->data_vec[ix];
+	refcount = kref_read(&entry->kref);
+
+	write_unlock_irq(&table->rwlock);
+
+	if (refcount > 1) {
+		pr_debug("%s: The GID table is still referenced and cannot be deleted.\n",
+			__func__);
+		return true;
+	} else {
+		return false;
+	}
+}
+
 static int
 _ib_cache_gid_del(struct ib_device *ib_dev, u32 port,
 		  union ib_gid *gid, struct ib_gid_attr *attr,
@@ -615,6 +643,9 @@ _ib_cache_gid_del(struct ib_device *ib_dev, u32 port,
 		goto out_unlock;
 	}
 
+	if (gid_table_is_shared(table, ix))
+		goto out_unlock;
+
 	del_gid(ib_dev, port, table, ix);
 	dispatch_gid_change_event(ib_dev, port);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-05-18 17:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-13  8:07 [PATCH] IB/cache: Check GID table references before attempting deletion Chenguang Zhao
2026-05-17 10:32 ` Leon Romanovsky
2026-05-18  2:36   ` Chenguang Zhao
2026-05-18 17:58     ` Jason Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox