mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 08:12:27 -04:00
vfs: make vfscount refcounting handle possible kld unload
Make the refcounting occur outside any code that might deref a pointer to struct vfsconf. Increment vfc_refcount in vfs_byname(), under vfsconf_lock. Unref either on early mount failure, before struct mount is instantiated, or in vfs_mount_destroy(). Reported and reviewed by: kevans Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week
This commit is contained in:
parent
959806e0a8
commit
be8bae6700
3 changed files with 20 additions and 4 deletions
|
|
@ -103,6 +103,16 @@ struct vattr va_null;
|
|||
* Routines having to do with the management of the vnode table.
|
||||
*/
|
||||
|
||||
void
|
||||
vfs_unref_vfsconf(struct vfsconf *vfsp)
|
||||
{
|
||||
vfsconf_lock();
|
||||
KASSERT(vfsp->vfc_refcount > 0,
|
||||
("vfs %p refcount underflow %d", vfsp, vfsp->vfc_refcount));
|
||||
vfsp->vfc_refcount--;
|
||||
vfsconf_unlock();
|
||||
}
|
||||
|
||||
static struct vfsconf *
|
||||
vfs_byname_locked(const char *name)
|
||||
{
|
||||
|
|
@ -123,9 +133,11 @@ vfs_byname(const char *name)
|
|||
{
|
||||
struct vfsconf *vfsp;
|
||||
|
||||
vfsconf_slock();
|
||||
vfsconf_lock();
|
||||
vfsp = vfs_byname_locked(name);
|
||||
vfsconf_sunlock();
|
||||
if (vfsp != NULL)
|
||||
vfsp->vfc_refcount++;
|
||||
vfsconf_unlock();
|
||||
return (vfsp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -683,7 +683,6 @@ vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, const char *fspath,
|
|||
MPASSERT(mp->mnt_vfs_ops == 1, mp,
|
||||
("vfs_ops should be 1 but %d found", mp->mnt_vfs_ops));
|
||||
(void) vfs_busy(mp, MBF_NOWAIT);
|
||||
atomic_add_acq_int(&vfsp->vfc_refcount, 1);
|
||||
mp->mnt_op = vfsp->vfc_vfsops;
|
||||
mp->mnt_vfc = vfsp;
|
||||
mp->mnt_stat.f_type = vfsp->vfc_typenum;
|
||||
|
|
@ -731,7 +730,6 @@ vfs_mount_destroy(struct mount *mp)
|
|||
__FILE__, __LINE__));
|
||||
MPPASS(mp->mnt_writeopcount == 0, mp);
|
||||
MPPASS(mp->mnt_secondary_writes == 0, mp);
|
||||
atomic_subtract_rel_int(&mp->mnt_vfc->vfc_refcount, 1);
|
||||
if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
|
||||
struct vnode *vp;
|
||||
|
||||
|
|
@ -769,6 +767,9 @@ vfs_mount_destroy(struct mount *mp)
|
|||
vfs_free_addrlist(mp->mnt_export);
|
||||
free(mp->mnt_export, M_MOUNT);
|
||||
}
|
||||
vfsconf_lock();
|
||||
mp->mnt_vfc->vfc_refcount--;
|
||||
vfsconf_unlock();
|
||||
crfree(mp->mnt_cred);
|
||||
uma_zfree(mount_zone, mp);
|
||||
}
|
||||
|
|
@ -1133,6 +1134,7 @@ vfs_domount_first(
|
|||
if (jailed(td->td_ucred) && (!prison_allow(td->td_ucred,
|
||||
vfsp->vfc_prison_flag) || vp == td->td_ucred->cr_prison->pr_root)) {
|
||||
vput(vp);
|
||||
vfs_unref_vfsconf(vfsp);
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
|
|
@ -1169,6 +1171,7 @@ vfs_domount_first(
|
|||
}
|
||||
if (error != 0) {
|
||||
vput(vp);
|
||||
vfs_unref_vfsconf(vfsp);
|
||||
return (error);
|
||||
}
|
||||
vn_seqc_write_begin(vp);
|
||||
|
|
|
|||
|
|
@ -1007,6 +1007,7 @@ struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val,
|
|||
void statfs_scale_blocks(struct statfs *sf, long max_size);
|
||||
struct vfsconf *vfs_byname(const char *);
|
||||
struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *);
|
||||
void vfs_unref_vfsconf(struct vfsconf *vfsp);
|
||||
void vfs_mount_destroy(struct mount *);
|
||||
void vfs_event_signal(fsid_t *, u_int32_t, intptr_t);
|
||||
void vfs_freeopts(struct vfsoptlist *opts);
|
||||
|
|
|
|||
Loading…
Reference in a new issue