diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2025-06-03 20:01:24 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2025-06-05 22:41:40 +0000 |
| commit | e9897199576a40360440aa4d2aa48d61c4010f11 (patch) | |
| tree | 069ea254032898785245014a43397c6fce0a812a | |
| parent | b63f298b1ff90d9c25dee09df7fdd0e509185587 (diff) | |
pseudofs: make dup name an error instead of panic
There are enough cases where the duplicate name is caused by dubious
hardware configuration. Stopping the whole system instead of failing a
driver, or even a diagnostic subsystem in a driver, is more
user-friendly.
Another issue right now is that the check is only present for the
INVARIANTS builds, silently accepting the request to create an entry
with the existing name on production builds.
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D50669
| -rw-r--r-- | sys/fs/pseudofs/pseudofs.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/sys/fs/pseudofs/pseudofs.c b/sys/fs/pseudofs/pseudofs.c index eafa2947490a..ef45f96a6192 100644 --- a/sys/fs/pseudofs/pseudofs.c +++ b/sys/fs/pseudofs/pseudofs.c @@ -98,12 +98,10 @@ pfs_alloc_node(struct pfs_info *pi, const char *name, pfs_type_t type) /* * Add a node to a directory */ -static void +static int pfs_add_node(struct pfs_node *parent, struct pfs_node *pn) { -#ifdef INVARIANTS struct pfs_node *iter; -#endif KASSERT(parent != NULL, ("%s(): parent is NULL", __func__)); @@ -123,9 +121,6 @@ pfs_add_node(struct pfs_node *parent, struct pfs_node *pn) KASSERT(iter->pn_type != pfstype_procdir, ("%s(): nested process directories", __func__)); for (iter = parent->pn_nodes; iter != NULL; iter = iter->pn_next) { - KASSERT(strcmp(pn->pn_name, iter->pn_name) != 0, - ("%s(): homonymous siblings: '%s' type %d", __func__, - pn->pn_name, pn->pn_type)); if (pn->pn_type == pfstype_procdir) KASSERT(iter->pn_type != pfstype_procdir, ("%s(): sibling process directories", __func__)); @@ -134,8 +129,19 @@ pfs_add_node(struct pfs_node *parent, struct pfs_node *pn) pn->pn_parent = parent; pfs_fileno_alloc(pn); - pfs_lock(parent); + for (iter = parent->pn_nodes; iter != NULL; iter = iter->pn_next) { + if (strcmp(pn->pn_name, iter->pn_name) != 0) + continue; + printf("pfs_add_node: homonymous siblings: '%s/%s' type %d", + parent->pn_name, pn->pn_name, pn->pn_type); + /* Do not detach, because we are not yet attached. */ + pn->pn_parent = NULL; + pfs_unlock(parent); + return (EEXIST); + } + + if ((parent->pn_flags & PFS_PROCDEP) != 0) pn->pn_flags |= PFS_PROCDEP; if (parent->pn_nodes == NULL) { @@ -152,6 +158,7 @@ pfs_add_node(struct pfs_node *parent, struct pfs_node *pn) parent->pn_last_node = pn; } pfs_unlock(parent); + return (0); } /* @@ -197,6 +204,7 @@ static int pfs_fixup_dir_flags(struct pfs_node *parent, int flags) { struct pfs_node *dot, *dotdot; + int rc; dot = pfs_alloc_node_flags(parent->pn_info, ".", pfstype_this, flags); if (dot == NULL) @@ -206,9 +214,14 @@ pfs_fixup_dir_flags(struct pfs_node *parent, int flags) pfs_destroy(dot); return (ENOMEM); } - pfs_add_node(parent, dot); - pfs_add_node(parent, dotdot); - return (0); + rc = pfs_add_node(parent, dot); + if (rc == 0) + rc = pfs_add_node(parent, dotdot); + if (rc != 0) { + pfs_destroy(dot); + pfs_destroy(dotdot); + } + return (rc); } static void @@ -237,11 +250,12 @@ pfs_create_dir(struct pfs_node *parent, const char *name, pn->pn_vis = vis; pn->pn_destroy = destroy; pn->pn_flags = flags; - pfs_add_node(parent, pn); - rc = pfs_fixup_dir_flags(pn, flags); - if (rc) { + rc = pfs_add_node(parent, pn); + if (rc == 0) + rc = pfs_fixup_dir_flags(pn, flags); + if (rc != 0) { pfs_destroy(pn); - return (NULL); + pn = NULL; } return (pn); } @@ -264,8 +278,10 @@ pfs_create_file(struct pfs_node *parent, const char *name, pfs_fill_t fill, pn->pn_vis = vis; pn->pn_destroy = destroy; pn->pn_flags = flags; - pfs_add_node(parent, pn); - + if (pfs_add_node(parent, pn) != 0) { + pfs_destroy(pn); + pn = NULL; + } return (pn); } @@ -287,7 +303,10 @@ pfs_create_link(struct pfs_node *parent, const char *name, pfs_fill_t fill, pn->pn_vis = vis; pn->pn_destroy = destroy; pn->pn_flags = flags; - pfs_add_node(parent, pn); + if (pfs_add_node(parent, pn) != 0) { + pfs_destroy(pn); + pn = NULL; + } return (pn); } |
