devfs: add anonymous variants to register/remove

The current devfs code requires registered devices to have a name on
creation. This makes temporary/hidden devices like pty master ends
appear for a split second on the devfs tree.

Add a way of registering/removing devfs nodes which do not have a name
on the tree.
This commit is contained in:
Matheus
2026-10-05 14:33:30 -03:00
parent d1765b22b5
commit 1c65a2c891
2 changed files with 52 additions and 2 deletions
+46 -1
View File
@@ -527,8 +527,41 @@ int devfs_getbyname(char *name, vnode_t **ret) {
cleanup:
return error;
}
int devfs_register_anonymous(devops_t *devops, int type, int major, int minor, mode_t mode,
cred_t *cred, vnode_t **out) {
__assert(type == V_TYPE_CHDEV || type == V_TYPE_BLKDEV);
devnode_t *master = slab_allocate(nodecache);
if (master == NULL)
return ENOMEM;
master->vnode.type = type;
master->devops = devops;
master->attr.mode = mode;
master->attr.rdevmajor = major;
master->attr.rdevminor = minor;
master->attr.uid = cred == NULL ? 0 : cred->euid;
master->attr.gid = cred == NULL ? 0 : cred->egid;
int key[2] = {major, minor};
MUTEX_ACQUIRE(&tablelock);
int error = hashtable_set(&devtable, master, key, sizeof(key), true);
MUTEX_RELEASE(&tablelock);
if (error) {
destroy_node(master);
return error;
}
VOP_HOLD(&master->vnode);
*out = &master->vnode;
return 0;
}
// register new device
int devfs_register(devops_t *devops, char *name, int type, int major, int minor, mode_t mode, cred_t *cred) {
int devfs_register(devops_t *devops, char *name, int type, int major, int minor, mode_t mode,
cred_t *cred) {
__assert(type == V_TYPE_CHDEV || type == V_TYPE_BLKDEV);
devnode_t *master = slab_allocate(nodecache);
if (master == NULL)
@@ -613,6 +646,18 @@ int devfs_getnode(vnode_t *physical, int major, int minor, vnode_t **node) {
return 0;
}
void devfs_remove_anonymous(int major, int minor) {
int key[2] = {major, minor};
void *master;
MUTEX_ACQUIRE(&tablelock);
__assert(hashtable_get(&devtable, &master, key, sizeof(key)) == 0);
__assert(hashtable_remove(&devtable, key, sizeof(key)) == 0);
MUTEX_RELEASE(&tablelock);
vnode_t *vnode = master;
VOP_RELEASE(vnode);
}
void devfs_remove(char *name, int major, int minor) {
int key[2] = {major, minor};
// remove devtable reference
+6 -1
View File
@@ -23,6 +23,7 @@
#define DEV_MAJOR_PROF 14
#define DEV_MAJOR_INPUT 15
#define DEV_MAJOR_AUDIO 16
#define DEV_MAJOR_KCOV 17
typedef struct {
int (*open)(int minor, vnode_t **vnode, int flags);
@@ -49,9 +50,13 @@ typedef struct devnode_t {
void devfs_init();
int devfs_getnode(vnode_t *physical, int major, int minor, vnode_t **node);
int devfs_register(devops_t *devops, char *name, int type, int major, int minor, mode_t mode, cred_t *cred);
int devfs_register_anonymous(devops_t *devops, int type, int major, int minor, mode_t mode,
cred_t *cred, vnode_t **out);
int devfs_register(devops_t *devops, char *name, int type, int major, int minor, mode_t mode,
cred_t *cred);
int devfs_getbyname(char *name, vnode_t **ret);
int devfs_createdir(char *name);
void devfs_remove_anonymous(int major, int minor);
void devfs_remove(char *name, int major, int minor);
#endif