From nobody Tue Feb 10 01:23:07 2026 Received: from mail-ot1-f41.google.com (mail-ot1-f41.google.com [209.85.210.41]) (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 8C18325D216 for ; Tue, 2 Dec 2025 15:29:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764689365; cv=none; b=DQOmNFtCqFz2VhOJZe9SqdYO8aTnjCu6TCY/5qnHuWRnM8o8qfdttGzfnGwhERQOsIxISmsZkxSlCxXB85wM3akXOlBAOLrYz2oBPqXYCcDli1q2Yr2NLx3TOKgv42s2vmOr78OECJMOF653Vu6cWw6UEdREEoxju1arZVziZnI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764689365; c=relaxed/simple; bh=FIYqGpM1IyGqClwriylZkCgR358j3T2vsImf6FPQdBA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Uu7bzjjFSHpeODQ4vpXFIJtU8Oi9wMq2cWoBf5DUloyXUxIKm1IFjVJB2zUbGkzYmNKV1g8nailAv9vXwGS3fAK925XF77XRvg6j+HMt3GJms5eoGItpGHBeB6SuDsqseMCiw1T3RDOm/Eqr2RhDVsjKgt+HsC1he/ZaFtv92KU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.210.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f41.google.com with SMTP id 46e09a7af769-7c77fc7c11bso4670588a34.1 for ; Tue, 02 Dec 2025 07:29:23 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764689362; x=1765294162; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=A6kRcsSTxQVe89CZtHebxpViGYsgG9Ml2myNrOME/Lo=; b=WQuxUYc0edrC+ljlLOAKANLIo+j8t71PJABfhuwvVnE7v3rX519MFBBK1TFP36kpDR fH6PVT7xzWP9iWTPE88Vww8VwGeUAjS2yZo9n5BaBVNXR9KbNpjF6rM7T0K4HOINzEoo HDbB7Knzph1A3buGut79Hf1QmD71uSDTprSy+RCGJ0+POM7sqOJwJeDYo3InKrjEnrQ5 GGdj4ESMOeM2oCkhjXizC1/e36X1LbE+907tGZaPZbyIugEWuOIOzqoog37z6+MLrjXI unNdyJxX9DYahLNi29c561Mw/GZYoQUpFg3VyjBKDHxZRgqApaCq8MCm9uPNaJYDyY0e si+w== X-Forwarded-Encrypted: i=1; AJvYcCUbbl/zafoIOHhL0LonsB/gB6IN9wcc424adSWvF7dwC/aZgqQbYEOnCXnpfi8Hh7LsNXopknpoE+hgc6w=@vger.kernel.org X-Gm-Message-State: AOJu0YzLjQ+7XDFTZg0PZn2CVOzyGMS5FNytjjdN+qzSuf02mT3rlzNZ wp6Qtq1JcSx3qPiPOPihuIyVy0uFooRYqqKm072PZdu9JRMsVwJH3IPo X-Gm-Gg: ASbGncvwLACeGVMQOpWh20lZgPRjD01BoAr5W1AbAk+mjGyD9tAJmnb/9gzzwjzchoN r/dvAmK/dDKTQOHgRSeHkAPmy+lmwxaOH3fwZntHZO08VzVaOVv69t4h4VM1Ql71vpxC7G9ymEh Vq41ifCVE/DEeCiibXzLdgbbh0nryjZpI/OQK6mpuQSqWiH3VtHmnDlYCbBQ7q/jyXtBLyDRxuV +i/fGNoS7Oru3jFOGBP5lu20sSQzRc/OuakhGnI5OF7vjKJwJ/+x/YsbTj7ojsCtm515g092LOo FEedesV9NV19YFPCtmr1JR3NJKZc0cAquFRvdVRif92jnojEtCakDZe6S9UXKGsG7VpjrbKA5Uh PR7XP5nDM1l3VK2Csg5E7cS0bmXMO2uHCWXc/bcoekQw34dO9rYyPdZ9Zv8EnfuXBpe4gZNxhu6 I6GaO+8Jc9971hUA== X-Google-Smtp-Source: AGHT+IFx57reYompYCqN3lfJy/5+1CqSdFB86fexumX1BX8BCuA0OEnC2uBr5WnT+XMeBOsfVkmfcw== X-Received: by 2002:a05:6830:270d:b0:785:6792:4b3 with SMTP id 46e09a7af769-7c9406dc93amr1942186a34.10.1764689362374; Tue, 02 Dec 2025 07:29:22 -0800 (PST) Received: from localhost ([2a03:2880:10ff:74::]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-65933cc55bfsm4299080eaf.9.2025.12.02.07.29.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 07:29:21 -0800 (PST) From: Breno Leitao Date: Tue, 02 Dec 2025 07:29:01 -0800 Subject: [PATCH RFC 1/2] configfs: add kernel-space item registration API 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" Content-Transfer-Encoding: quoted-printable Message-Id: <20251202-configfs_netcon-v1-1-b4738ead8ee8@debian.org> References: <20251202-configfs_netcon-v1-0-b4738ead8ee8@debian.org> In-Reply-To: <20251202-configfs_netcon-v1-0-b4738ead8ee8@debian.org> To: Andreas Hindborg , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: Breno Leitao , linux-kernel@vger.kernel.org, hch@infradead.org, jlbec@evilplan.org, linux-fsdevel@vger.kernel.org, netdev@vger.kernel.org, gustavold@gmail.com, asantostc@gmail.com, calvin@wbinvd.org, kernel-team@meta.com X-Mailer: b4 0.15-dev-a6db3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5783; i=leitao@debian.org; h=from:subject:message-id; bh=FIYqGpM1IyGqClwriylZkCgR358j3T2vsImf6FPQdBA=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBpLwXQ6xc3qGvZPhOLjly3a7HHfPBIXQpUMV4A+ /no/PNlsDCJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaS8F0AAKCRA1o5Of/Hh3 bWL3D/4oiGW5RJtPOPyG2heY+nT1odkK8dnPj8xUzIc6BovFbB2WI6FBoRXaoL+UM5LJzLSojth C0zVZNbr5uz49zIw7tn/WHqgj31P3qbqY98SW3pFXXrTH0joU5d+YJ55e5TQkCLEwR61hZUf0Q2 mabZzzayBd0EQFJnAV3dXajJ6Zdvs/9vBWZpds/IzVngfHflikZNDXIvhU29xpgTq0zt1oKcCo7 PLzDld+onH7yM/5/4GoXSQ7wfbYpUL6p7MkMrGNd5D0HavShC5iL4DA9/44xnLu+kf+J5QuIKeN yyHINRhmxhXkh9W3Px6DjzKisweAWoYFW7BF5MY7hxzZ8yr1ll5wsnPcDAlvOyZbFVTrbW5zWrb SmyfoFeNSpp7Bv5704LHOrgksFHoeJHQJl19xAHceWszyqgzXtggsQajFyFB+cjhD9JwJsU8x2T 3T5vmsiQiyCF0gWKtyoliv0htkK27FVdlXRVQNG5zXS8Wdbm7G1AvhHYTL0Mizl737iHAiLf8J3 Iw4C+pE6SLyxW5l7pu1jKGv9ke7i95TmixNnj1To9QWXHheC3mWcVATCa29PHcRKzBRpQcMTQAU RdzVEuJDSPRcj5o5lAED8+36HawbkBzEhmyQxORPac47+/X8RTVFpnYOeRJjUrQFJVxkcEW/B8D +fMAHSlLn/0Cd6Q== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D Add configfs_register_item() and configfs_unregister_item() functions to allow kernel modules to register configfs items whose lifecycle is controlled by kernel space rather than userspace. This is useful for subsystems that need to expose configuration items that are created based on kernel events (like boot parameters) rather than explicit userspace mkdir operations. The items registered this way are marked as default items (CONFIGFS_USET_DEFAULT) and cannot be removed via rmdir. The API follows the same pattern as configfs_register_group() but for individual items: - configfs_register_item() links the item into the parent group's hierarchy and creates the filesystem representation - configfs_unregister_item() reverses the registration, removing the item from configfs Signed-off-by: Breno Leitao --- fs/configfs/dir.c | 134 +++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/configfs.h | 4 +++ 2 files changed, 138 insertions(+) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 81f4f06bc87e..f7224bc51826 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -1866,6 +1866,140 @@ void configfs_unregister_default_group(struct confi= g_group *group) } EXPORT_SYMBOL(configfs_unregister_default_group); =20 +/** + * configfs_register_item() - registers a kernel-created item with a paren= t group + * @parent_group: parent group for the new item + * @item: item to be registered + * + * This function allows kernel code to register configfs items whose lifec= ycle + * is controlled by kernel space rather than userspace (via mkdir/rmdir). + * The item must be already initialized with config_item_init_type_name(). + * + * Return: 0 on success, negative errno on failure + */ +int configfs_register_item(struct config_group *parent_group, + struct config_item *item) +{ + struct configfs_subsystem *subsys =3D parent_group->cg_subsys; + struct configfs_fragment *frag; + struct dentry *parent, *child; + struct configfs_dirent *sd; + int ret; + + if (!subsys || !item->ci_name) + return -EINVAL; + + frag =3D new_fragment(); + if (!frag) + return -ENOMEM; + + parent =3D parent_group->cg_item.ci_dentry; + /* Allocate dentry for the item */ + child =3D d_alloc_name(parent, item->ci_name); + if (!child) { + put_fragment(frag); + return -ENOMEM; + } + + mutex_lock(&subsys->su_mutex); + link_obj(&parent_group->cg_item, item); + mutex_unlock(&subsys->su_mutex); + + inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); + d_add(child, NULL); + + /* Attach the item to the filesystem */ + ret =3D configfs_attach_item(&parent_group->cg_item, item, child, frag); + if (ret) + goto err_out; + + /* + * CONFIGFS_USET_DEFAULT mark item as kernel-created (cannot be removed + * by userspace) + */ + sd =3D child->d_fsdata; + sd->s_type |=3D CONFIGFS_USET_DEFAULT; + + /* Mark directory as ready */ + spin_lock(&configfs_dirent_lock); + configfs_dir_set_ready(child->d_fsdata); + spin_unlock(&configfs_dirent_lock); + + inode_unlock(d_inode(parent)); + put_fragment(frag); + return 0; + +err_out: + d_drop(child); + dput(child); + inode_unlock(d_inode(parent)); + mutex_lock(&subsys->su_mutex); + unlink_obj(item); + mutex_unlock(&subsys->su_mutex); + put_fragment(frag); + return ret; +} +EXPORT_SYMBOL(configfs_register_item); + +/** + * configfs_unregister_item() - unregisters a kernel-created item + * @item: item to be unregistered + * + * This function reverses the effect of configfs_register_item(), removing + * the item from the configfs filesystem and releasing associated resource= s. + * The item must have been previously registered with configfs_register_it= em(). + */ +void configfs_unregister_item(struct config_item *item) +{ + struct config_group *group =3D item->ci_group; + struct dentry *dentry =3D item->ci_dentry; + struct configfs_subsystem *subsys; + struct configfs_fragment *frag; + struct configfs_dirent *sd; + struct dentry *parent; + + if (!group || !dentry) + return; + + subsys =3D group->cg_subsys; + if (!subsys) + return; + + parent =3D item->ci_parent->ci_dentry; + sd =3D dentry->d_fsdata; + frag =3D get_fragment(sd->s_frag); + + if (WARN_ON(!(sd->s_type & CONFIGFS_USET_DEFAULT))) { + put_fragment(frag); + return; + } + + /* Mark fragment as dead */ + down_write(&frag->frag_sem); + frag->frag_dead =3D true; + up_write(&frag->frag_sem); + + inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); + spin_lock(&configfs_dirent_lock); + configfs_detach_prep(dentry, NULL); + spin_unlock(&configfs_dirent_lock); + + configfs_detach_item(item); + d_inode(dentry)->i_flags |=3D S_DEAD; + dont_mount(dentry); + d_drop(dentry); + fsnotify_rmdir(d_inode(parent), dentry); + dput(dentry); + inode_unlock(d_inode(parent)); + + mutex_lock(&subsys->su_mutex); + unlink_obj(item); + mutex_unlock(&subsys->su_mutex); + + put_fragment(frag); +} +EXPORT_SYMBOL(configfs_unregister_item); + int configfs_register_subsystem(struct configfs_subsystem *subsys) { int err; diff --git a/include/linux/configfs.h b/include/linux/configfs.h index 698520b1bfdb..70f2d113b4b3 100644 --- a/include/linux/configfs.h +++ b/include/linux/configfs.h @@ -244,6 +244,10 @@ int configfs_register_group(struct config_group *paren= t_group, struct config_group *group); void configfs_unregister_group(struct config_group *group); =20 +int configfs_register_item(struct config_group *parent_group, + struct config_item *item); +void configfs_unregister_item(struct config_item *item); + void configfs_remove_default_groups(struct config_group *group); =20 struct config_group * --=20 2.47.3