summaryrefslogtreecommitdiffstats
path: root/sys/gnu/ext2fs
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-05-18 22:18:17 +0000
committeriedowse <iedowse@FreeBSD.org>2002-05-18 22:18:17 +0000
commit807fc44381c5046d8c56e3d3a0bfedaf57959d94 (patch)
tree0388a15d6526b1649468898ffa0dde27f12de480 /sys/gnu/ext2fs
parent798b0bf42f105e35c6f8eaf7e21a8be6b93fcf09 (diff)
downloadFreeBSD-src-807fc44381c5046d8c56e3d3a0bfedaf57959d94.zip
FreeBSD-src-807fc44381c5046d8c56e3d3a0bfedaf57959d94.tar.gz
Add an ext2_uninit() routine that undoes the actions performed by
ext2_init(). This permits the ext2fs module to be unloaded without causing panics and leaking memory.
Diffstat (limited to 'sys/gnu/ext2fs')
-rw-r--r--sys/gnu/ext2fs/ext2_extern.h1
-rw-r--r--sys/gnu/ext2fs/ext2_ihash.c17
-rw-r--r--sys/gnu/ext2fs/ext2_vfsops.c14
3 files changed, 27 insertions, 5 deletions
diff --git a/sys/gnu/ext2fs/ext2_extern.h b/sys/gnu/ext2fs/ext2_extern.h
index 54293db..a8fcf09 100644
--- a/sys/gnu/ext2fs/ext2_extern.h
+++ b/sys/gnu/ext2fs/ext2_extern.h
@@ -69,6 +69,7 @@ void ext2_ihashins(struct inode *);
struct vnode *
ext2_ihashlookup(dev_t, ino_t);
void ext2_ihashrem(struct inode *);
+void ext2_ihashuninit(void);
void ext2_itimes(struct vnode *vp);
int ext2_reallocblks(struct vop_reallocblks_args *);
int ext2_reclaim(struct vop_reclaim_args *);
diff --git a/sys/gnu/ext2fs/ext2_ihash.c b/sys/gnu/ext2fs/ext2_ihash.c
index d11d4dc..d404e15 100644
--- a/sys/gnu/ext2fs/ext2_ihash.c
+++ b/sys/gnu/ext2fs/ext2_ihash.c
@@ -62,11 +62,28 @@ void
ext2_ihashinit()
{
+ KASSERT(ihashtbl == NULL, ("ext2_ihashinit called twice"));
ihashtbl = hashinit(desiredvnodes, M_EXT2IHASH, &ihash);
mtx_init(&ext2_ihash_mtx, "ext2 ihash", NULL, MTX_DEF);
}
/*
+ * Destroy the inode hash table.
+ */
+void
+ext2_ihashuninit()
+{
+ struct ihashhead *hp;
+
+ for (hp = ihashtbl; hp < &ihashtbl[ihash]; hp++)
+ if (!LIST_EMPTY(hp))
+ panic("ext2_ihashuninit: ihash not empty");
+ free(ihashtbl, M_EXT2IHASH);
+ ihashtbl = NULL;
+ mtx_destroy(&ext2_ihash_mtx);
+}
+
+/*
* Use the device/inum pair to find the incore inode, and return a pointer
* to it. If it is in core, return it, even if it is locked.
*/
diff --git a/sys/gnu/ext2fs/ext2_vfsops.c b/sys/gnu/ext2fs/ext2_vfsops.c
index a5cbefc..f23a7c1 100644
--- a/sys/gnu/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/ext2fs/ext2_vfsops.c
@@ -75,6 +75,7 @@ static int ext2_root(struct mount *, struct vnode **vpp);
static int ext2_sbupdate(struct ext2mount *, int);
static int ext2_statfs(struct mount *, struct statfs *, struct thread *);
static int ext2_sync(struct mount *, int, struct ucred *, struct thread *);
+static int ext2_uninit(struct vfsconf *);
static int ext2_unmount(struct mount *, int, struct thread *);
static int ext2_vget(struct mount *, ino_t, int, struct vnode **);
static int ext2_vptofh(struct vnode *, struct fid *);
@@ -95,7 +96,7 @@ static struct vfsops ext2fs_vfsops = {
vfs_stdcheckexp,
ext2_vptofh,
ext2_init,
- vfs_stduninit,
+ ext2_uninit,
vfs_stdextattrctl,
};
@@ -1207,12 +1208,15 @@ ext2_root(mp, vpp)
static int
ext2_init(struct vfsconf *vfsp)
{
- static int done;
- if (done)
- return (0);
- done = 1;
ext2_ihashinit();
+ return (0);
+}
+
+static int
+ext2_uninit(struct vfsconf *vfsp)
+{
+ ext2_ihashuninit();
return (0);
}
OpenPOWER on IntegriCloud