When DEVLINK_CMD_REGION_NEW is issued without a snapshot id, the kernel allocates one with __devlink_region_snapshot_id_get(). That helper counts the caller as a user of the id, and the caller must release this hold once it is done. devlink_nl_region_new_doit() never drops it. The refcount of the id goes 1 (allocation) -> 2 (snapshot created) and stays at 2. When the snapshot is deleted the count only drops to 1, so the id is never erased from the snapshot_ids xarray. The id then stays in use for the lifetime of the devlink instance: requesting a snapshot with that explicit id fails with -EEXIST, and there is no snapshot left to delete to clean it up. Reproducer steps: # devlink region new pci/0000:13:00.0/device-caps pci/0000:13:00.0/device-caps: snapshot 0 # devlink region del pci/0000:13:00.0/device-caps snapshot 0 # devlink region new pci/0000:13:00.0/device-caps snapshot 0 kernel answers: File exists Drop the caller's reference right after the snapshot has been created, as the snapshot then holds its own. Fixes: 043b3e22768d ("devlink: let kernel allocate region snapshot id") Reported-by: Guikun Yang Closes: https://lore.kernel.org/netdev/tencent_BE912BA710539F285F9FCF28E854ABEFCD07@qq.com/ Signed-off-by: Fernando Fernandez Mancera --- net/devlink/region.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/devlink/region.c b/net/devlink/region.c index 537779bbff07..c22016f23a4a 100644 --- a/net/devlink/region.c +++ b/net/devlink/region.c @@ -719,6 +719,11 @@ int devlink_nl_region_new_doit(struct sk_buff *skb, struct genl_info *info) if (!snapshot_id_attr) { struct sk_buff *msg; + /* Drop the allocation reference, the snapshot + * now holds its own. + */ + __devlink_snapshot_id_decrement(devlink, snapshot_id); + snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); if (WARN_ON(!snapshot)) { -- 2.56.0