git: 53a777bb52e3 - main - unionfs: do not create a new status object during vop_close()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 13 Jul 2024 01:39:51 UTC
The branch main has been updated by jah: URL: https://cgit.FreeBSD.org/src/commit/?id=53a777bb52e3f1e8a29fa0cbea9b991daf7ba01e commit 53a777bb52e3f1e8a29fa0cbea9b991daf7ba01e Author: Jason A. Harmening <jah@FreeBSD.org> AuthorDate: 2024-06-14 21:01:22 +0000 Commit: Jason A. Harmening <jah@FreeBSD.org> CommitDate: 2024-07-12 22:05:16 +0000 unionfs: do not create a new status object during vop_close() Split the portion of unionfs_get_node_status() that searches for an existing status object into a new helper function, unionfs_find_node_status(), and use that in unionfs_close(). Additionally, modify unionfs_close() to accept a NULL status object if unionfs_find_node_status() does not find a matching status object. This can happen due to the unconditional VOP_CLOSE() operation issued by vgonel(). Differential Revision: https://reviews.freebsd.org/D45398 Reviewed by: olce Tested by: pho --- sys/fs/unionfs/union.h | 2 ++ sys/fs/unionfs/union_subr.c | 45 ++++++++++++++++++++++++++++++-------------- sys/fs/unionfs/union_vnops.c | 9 +++++++-- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/sys/fs/unionfs/union.h b/sys/fs/unionfs/union.h index c535a3b288b8..0bd1894a2195 100644 --- a/sys/fs/unionfs/union.h +++ b/sys/fs/unionfs/union.h @@ -133,6 +133,8 @@ int unionfs_uninit(struct vfsconf *); int unionfs_nodeget(struct mount *, struct vnode *, struct vnode *, struct vnode *, struct vnode **, struct componentname *); void unionfs_noderem(struct vnode *); +struct unionfs_node_status * unionfs_find_node_status(struct unionfs_node *, + struct thread *td); void unionfs_get_node_status(struct unionfs_node *, struct thread *, struct unionfs_node_status **); void unionfs_tryrem_node_status(struct unionfs_node *, diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index 671322704dc5..e02dd547f249 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -578,35 +578,52 @@ unionfs_noderem(struct vnode *vp) } /* - * Get the unionfs node status object for the vnode corresponding to unp, - * for the process that owns td. Allocate a new status object if one - * does not already exist. + * Find the unionfs node status object for the vnode corresponding to unp, + * for the process that owns td. Return NULL if no such object exists. */ -void -unionfs_get_node_status(struct unionfs_node *unp, struct thread *td, - struct unionfs_node_status **unspp) +struct unionfs_node_status * +unionfs_find_node_status(struct unionfs_node *unp, struct thread *td) { struct unionfs_node_status *unsp; pid_t pid; pid = td->td_proc->p_pid; - KASSERT(NULL != unspp, ("%s: NULL status", __func__)); ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), __func__); LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) { if (unsp->uns_pid == pid) { - *unspp = unsp; - return; + return (unsp); } } - /* create a new unionfs node status */ - unsp = malloc(sizeof(struct unionfs_node_status), - M_TEMP, M_WAITOK | M_ZERO); + return (NULL); +} + +/* + * Get the unionfs node status object for the vnode corresponding to unp, + * for the process that owns td. Allocate a new status object if one + * does not already exist. + */ +void +unionfs_get_node_status(struct unionfs_node *unp, struct thread *td, + struct unionfs_node_status **unspp) +{ + struct unionfs_node_status *unsp; + pid_t pid; + + pid = td->td_proc->p_pid; - unsp->uns_pid = pid; - LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list); + KASSERT(NULL != unspp, ("%s: NULL status", __func__)); + unsp = unionfs_find_node_status(unp, td); + if (unsp == NULL) { + /* create a new unionfs node status */ + unsp = malloc(sizeof(struct unionfs_node_status), + M_TEMP, M_WAITOK | M_ZERO); + + unsp->uns_pid = pid; + LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list); + } *unspp = unsp; } diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index ae1d3946266d..3f39352ea5c0 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -793,9 +793,14 @@ unionfs_close(struct vop_close_args *ap) unp = VTOUNIONFS(vp); lvp = unp->un_lowervp; uvp = unp->un_uppervp; - unionfs_get_node_status(unp, td, &unsp); + unsp = unionfs_find_node_status(unp, td); - if (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0) { + if (unsp == NULL || + (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0)) { +#ifdef DIAGNOSTIC + if (unsp != NULL) + printf("unionfs_close: warning: open count is 0\n"); +#endif if (uvp != NULLVP) ovp = uvp; else