summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files1
-rw-r--r--sys/gnu/ext2fs/ext2_extern.h7
-rw-r--r--sys/gnu/ext2fs/ext2_ihash.c8
-rw-r--r--sys/gnu/ext2fs/ext2_inode.c5
-rw-r--r--sys/gnu/ext2fs/ext2_vfsops.c80
-rw-r--r--sys/gnu/fs/ext2fs/ext2_extern.h7
-rw-r--r--sys/gnu/fs/ext2fs/ext2_inode.c5
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c80
-rw-r--r--sys/modules/ext2fs/Makefile2
9 files changed, 61 insertions, 134 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 6e95f1f..c231006 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1003,7 +1003,6 @@ gnu/ext2fs/ext2_alloc.c optional ext2fs \
warning "kernel contains GPL contaminated ext2fs filesystem"
gnu/ext2fs/ext2_balloc.c optional ext2fs
gnu/ext2fs/ext2_bmap.c optional ext2fs
-gnu/ext2fs/ext2_ihash.c optional ext2fs
gnu/ext2fs/ext2_inode.c optional ext2fs
gnu/ext2fs/ext2_inode_cnv.c optional ext2fs
gnu/ext2fs/ext2_linux_balloc.c optional ext2fs
diff --git a/sys/gnu/ext2fs/ext2_extern.h b/sys/gnu/ext2fs/ext2_extern.h
index 367b633..24c8f45 100644
--- a/sys/gnu/ext2fs/ext2_extern.h
+++ b/sys/gnu/ext2fs/ext2_extern.h
@@ -59,13 +59,6 @@ void ext2_dirbad(struct inode *ip, doff_t offset, char *how);
void ext2_ei2i(struct ext2_inode *, struct inode *);
int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *);
void ext2_i2ei(struct inode *, struct ext2_inode *);
-int ext2_ihashget(struct cdev *, ino_t, int, struct vnode **);
-void ext2_ihashinit(void);
-void ext2_ihashins(struct inode *);
-struct vnode *
- ext2_ihashlookup(struct cdev *, 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 7bc049e..5106f37 100644
--- a/sys/gnu/ext2fs/ext2_ihash.c
+++ b/sys/gnu/ext2fs/ext2_ihash.c
@@ -48,7 +48,7 @@ static MALLOC_DEFINE(M_EXT2IHASH, "EXT2 ihash", "EXT2 Inode hash tables");
*/
static LIST_HEAD(ihashhead, inode) *ihashtbl;
static u_long ihash; /* size of hash table - 1 */
-#define INOHASH(device, inum) (&ihashtbl[(minor(device) + (inum)) & ihash])
+#define INOHASH(inum) (&ihashtbl[(inum) & ihash])
static struct mtx ext2_ihash_mtx;
/*
@@ -86,7 +86,7 @@ ext2_ihashlookup(dev, inum)
struct inode *ip;
mtx_lock(&ext2_ihash_mtx);
- LIST_FOREACH(ip, INOHASH(dev, inum), i_hash)
+ LIST_FOREACH(ip, INOHASH(inum), i_hash)
if (inum == ip->i_number && dev == ip->i_dev)
break;
mtx_unlock(&ext2_ihash_mtx);
@@ -115,7 +115,7 @@ ext2_ihashget(dev, inum, flags, vpp)
*vpp = NULL;
loop:
mtx_lock(&ext2_ihash_mtx);
- LIST_FOREACH(ip, INOHASH(dev, inum), i_hash) {
+ LIST_FOREACH(ip, INOHASH(inum), i_hash) {
if (inum == ip->i_number && dev == ip->i_dev) {
vp = ITOV(ip);
mtx_lock(&vp->v_interlock);
@@ -147,7 +147,7 @@ ext2_ihashins(ip)
vn_lock(ITOV(ip), LK_EXCLUSIVE | LK_RETRY, td);
mtx_lock(&ext2_ihash_mtx);
- ipp = INOHASH(ip->i_dev, ip->i_number);
+ ipp = INOHASH(ip->i_number);
LIST_INSERT_HEAD(ipp, ip, i_hash);
ip->i_flag |= IN_HASHED;
mtx_unlock(&ext2_ihash_mtx);
diff --git a/sys/gnu/ext2fs/ext2_inode.c b/sys/gnu/ext2fs/ext2_inode.c
index 2f48f9c..7a8e5e0 100644
--- a/sys/gnu/ext2fs/ext2_inode.c
+++ b/sys/gnu/ext2fs/ext2_inode.c
@@ -528,10 +528,7 @@ ext2_reclaim(ap)
ip->i_flag |= IN_MODIFIED;
ext2_update(vp, 0);
}
- /*
- * Remove the inode from its hash chain.
- */
- ext2_ihashrem(ip);
+ vfs_hash_remove(vp);
/*
* Purge old data structures associated with the inode.
*/
diff --git a/sys/gnu/ext2fs/ext2_vfsops.c b/sys/gnu/ext2fs/ext2_vfsops.c
index 1e73e12..81787f8 100644
--- a/sys/gnu/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/ext2fs/ext2_vfsops.c
@@ -74,8 +74,6 @@ static vfs_sync_t ext2_sync;
static vfs_vget_t ext2_vget;
static vfs_fhtovp_t ext2_fhtovp;
static vfs_vptofh_t ext2_vptofh;
-static vfs_init_t ext2_init;
-static vfs_uninit_t ext2_uninit;
static vfs_mount_t ext2_mount;
MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
@@ -83,12 +81,10 @@ static MALLOC_DEFINE(M_EXT2MNT, "EXT2 mount", "EXT2 mount structure");
static struct vfsops ext2fs_vfsops = {
.vfs_fhtovp = ext2_fhtovp,
- .vfs_init = ext2_init,
.vfs_mount = ext2_mount,
.vfs_root = ext2_root, /* root inode via vget */
.vfs_statfs = ext2_statfs,
.vfs_sync = ext2_sync,
- .vfs_uninit = ext2_uninit,
.vfs_unmount = ext2_unmount,
.vfs_vget = ext2_vget,
.vfs_vptofh = ext2_vptofh,
@@ -99,8 +95,6 @@ VFS_SET(ext2fs_vfsops, ext2fs, 0);
#define bsd_malloc malloc
#define bsd_free free
-static int ext2fs_inode_hash_lock;
-
static int ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev,
int ronly);
static int compute_sb_data(struct vnode * devvp,
@@ -921,27 +915,14 @@ ext2_vget(mp, ino, flags, vpp)
int i, error;
int used_blocks;
- ump = VFSTOEXT2(mp);
- dev = ump->um_dev;
-restart:
- if ((error = ext2_ihashget(dev, ino, flags, vpp)) != 0)
+ error = vfs_hash_get(mp, ino, flags, curthread, vpp);
+ if (error)
return (error);
if (*vpp != NULL)
return (0);
- /*
- * Lock out the creation of new entries in the FFS hash table in
- * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
- * may occur!
- */
- if (ext2fs_inode_hash_lock) {
- while (ext2fs_inode_hash_lock) {
- ext2fs_inode_hash_lock = -1;
- tsleep(&ext2fs_inode_hash_lock, PVM, "e2vget", 0);
- }
- goto restart;
- }
- ext2fs_inode_hash_lock = 1;
+ ump = VFSTOEXT2(mp);
+ dev = ump->um_dev;
/*
* If this MALLOC() is performed after the getnewvnode()
@@ -950,34 +931,43 @@ restart:
* which will cause a panic because ext2_sync() blindly
* dereferences vp->v_data (as well it should).
*/
- MALLOC(ip, struct inode *, sizeof(struct inode), M_EXT2NODE, M_WAITOK);
+ ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO);
/* Allocate a new vnode/inode. */
if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
- if (ext2fs_inode_hash_lock < 0)
- wakeup(&ext2fs_inode_hash_lock);
- ext2fs_inode_hash_lock = 0;
*vpp = NULL;
- FREE(ip, M_EXT2NODE);
+ free(ip, M_EXT2NODE);
return (error);
}
- bzero((caddr_t)ip, sizeof(struct inode));
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_e2fs = fs = ump->um_e2fs;
ip->i_dev = dev;
ip->i_number = ino;
+
/*
- * Put it onto its hash chain and lock it so that other requests for
- * this inode will block if they arrive while we are sleeping waiting
- * for old data structures to be purged or for the contents of the
- * disk portion of this inode to be read.
+ * Exclusively lock the vnode before adding to hash. Note, that we
+ * must not release nor downgrade the lock (despite flags argument
+ * says) till it is fully initialized.
*/
- ext2_ihashins(ip);
+ lockmgr(vp->v_vnlock, LK_EXCLUSIVE, (struct mtx *)0, curthread);
- if (ext2fs_inode_hash_lock < 0)
- wakeup(&ext2fs_inode_hash_lock);
- ext2fs_inode_hash_lock = 0;
+ /*
+ * Atomicaly (in terms of vfs_hash operations) check the hash for
+ * duplicate of vnode being created and add it to the hash. If a
+ * duplicate vnode was found, it will be vget()ed from hash for us.
+ */
+ if ((error = vfs_hash_insert(vp, ino, flags, curthread, vpp)) != 0) {
+ vput(vp);
+ *vpp = NULL;
+ return (error);
+ }
+
+ /* We lost the race, then throw away our vnode and return existing */
+ if (*vpp != NULL) {
+ vput(vp);
+ return (0);
+ }
/* Read in the disk contents for the inode, copy into the inode. */
#if 0
@@ -1159,19 +1149,3 @@ ext2_root(mp, vpp, td)
*vpp = nvp;
return (0);
}
-
-static int
-ext2_init(struct vfsconf *vfsp)
-{
-
- ext2_ihashinit();
- return (0);
-}
-
-static int
-ext2_uninit(struct vfsconf *vfsp)
-{
-
- ext2_ihashuninit();
- return (0);
-}
diff --git a/sys/gnu/fs/ext2fs/ext2_extern.h b/sys/gnu/fs/ext2fs/ext2_extern.h
index 367b633..24c8f45 100644
--- a/sys/gnu/fs/ext2fs/ext2_extern.h
+++ b/sys/gnu/fs/ext2fs/ext2_extern.h
@@ -59,13 +59,6 @@ void ext2_dirbad(struct inode *ip, doff_t offset, char *how);
void ext2_ei2i(struct ext2_inode *, struct inode *);
int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *);
void ext2_i2ei(struct inode *, struct ext2_inode *);
-int ext2_ihashget(struct cdev *, ino_t, int, struct vnode **);
-void ext2_ihashinit(void);
-void ext2_ihashins(struct inode *);
-struct vnode *
- ext2_ihashlookup(struct cdev *, 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/fs/ext2fs/ext2_inode.c b/sys/gnu/fs/ext2fs/ext2_inode.c
index 2f48f9c..7a8e5e0 100644
--- a/sys/gnu/fs/ext2fs/ext2_inode.c
+++ b/sys/gnu/fs/ext2fs/ext2_inode.c
@@ -528,10 +528,7 @@ ext2_reclaim(ap)
ip->i_flag |= IN_MODIFIED;
ext2_update(vp, 0);
}
- /*
- * Remove the inode from its hash chain.
- */
- ext2_ihashrem(ip);
+ vfs_hash_remove(vp);
/*
* Purge old data structures associated with the inode.
*/
diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c
index 1e73e12..81787f8 100644
--- a/sys/gnu/fs/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c
@@ -74,8 +74,6 @@ static vfs_sync_t ext2_sync;
static vfs_vget_t ext2_vget;
static vfs_fhtovp_t ext2_fhtovp;
static vfs_vptofh_t ext2_vptofh;
-static vfs_init_t ext2_init;
-static vfs_uninit_t ext2_uninit;
static vfs_mount_t ext2_mount;
MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
@@ -83,12 +81,10 @@ static MALLOC_DEFINE(M_EXT2MNT, "EXT2 mount", "EXT2 mount structure");
static struct vfsops ext2fs_vfsops = {
.vfs_fhtovp = ext2_fhtovp,
- .vfs_init = ext2_init,
.vfs_mount = ext2_mount,
.vfs_root = ext2_root, /* root inode via vget */
.vfs_statfs = ext2_statfs,
.vfs_sync = ext2_sync,
- .vfs_uninit = ext2_uninit,
.vfs_unmount = ext2_unmount,
.vfs_vget = ext2_vget,
.vfs_vptofh = ext2_vptofh,
@@ -99,8 +95,6 @@ VFS_SET(ext2fs_vfsops, ext2fs, 0);
#define bsd_malloc malloc
#define bsd_free free
-static int ext2fs_inode_hash_lock;
-
static int ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev,
int ronly);
static int compute_sb_data(struct vnode * devvp,
@@ -921,27 +915,14 @@ ext2_vget(mp, ino, flags, vpp)
int i, error;
int used_blocks;
- ump = VFSTOEXT2(mp);
- dev = ump->um_dev;
-restart:
- if ((error = ext2_ihashget(dev, ino, flags, vpp)) != 0)
+ error = vfs_hash_get(mp, ino, flags, curthread, vpp);
+ if (error)
return (error);
if (*vpp != NULL)
return (0);
- /*
- * Lock out the creation of new entries in the FFS hash table in
- * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
- * may occur!
- */
- if (ext2fs_inode_hash_lock) {
- while (ext2fs_inode_hash_lock) {
- ext2fs_inode_hash_lock = -1;
- tsleep(&ext2fs_inode_hash_lock, PVM, "e2vget", 0);
- }
- goto restart;
- }
- ext2fs_inode_hash_lock = 1;
+ ump = VFSTOEXT2(mp);
+ dev = ump->um_dev;
/*
* If this MALLOC() is performed after the getnewvnode()
@@ -950,34 +931,43 @@ restart:
* which will cause a panic because ext2_sync() blindly
* dereferences vp->v_data (as well it should).
*/
- MALLOC(ip, struct inode *, sizeof(struct inode), M_EXT2NODE, M_WAITOK);
+ ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO);
/* Allocate a new vnode/inode. */
if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
- if (ext2fs_inode_hash_lock < 0)
- wakeup(&ext2fs_inode_hash_lock);
- ext2fs_inode_hash_lock = 0;
*vpp = NULL;
- FREE(ip, M_EXT2NODE);
+ free(ip, M_EXT2NODE);
return (error);
}
- bzero((caddr_t)ip, sizeof(struct inode));
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_e2fs = fs = ump->um_e2fs;
ip->i_dev = dev;
ip->i_number = ino;
+
/*
- * Put it onto its hash chain and lock it so that other requests for
- * this inode will block if they arrive while we are sleeping waiting
- * for old data structures to be purged or for the contents of the
- * disk portion of this inode to be read.
+ * Exclusively lock the vnode before adding to hash. Note, that we
+ * must not release nor downgrade the lock (despite flags argument
+ * says) till it is fully initialized.
*/
- ext2_ihashins(ip);
+ lockmgr(vp->v_vnlock, LK_EXCLUSIVE, (struct mtx *)0, curthread);
- if (ext2fs_inode_hash_lock < 0)
- wakeup(&ext2fs_inode_hash_lock);
- ext2fs_inode_hash_lock = 0;
+ /*
+ * Atomicaly (in terms of vfs_hash operations) check the hash for
+ * duplicate of vnode being created and add it to the hash. If a
+ * duplicate vnode was found, it will be vget()ed from hash for us.
+ */
+ if ((error = vfs_hash_insert(vp, ino, flags, curthread, vpp)) != 0) {
+ vput(vp);
+ *vpp = NULL;
+ return (error);
+ }
+
+ /* We lost the race, then throw away our vnode and return existing */
+ if (*vpp != NULL) {
+ vput(vp);
+ return (0);
+ }
/* Read in the disk contents for the inode, copy into the inode. */
#if 0
@@ -1159,19 +1149,3 @@ ext2_root(mp, vpp, td)
*vpp = nvp;
return (0);
}
-
-static int
-ext2_init(struct vfsconf *vfsp)
-{
-
- ext2_ihashinit();
- return (0);
-}
-
-static int
-ext2_uninit(struct vfsconf *vfsp)
-{
-
- ext2_ihashuninit();
- return (0);
-}
diff --git a/sys/modules/ext2fs/Makefile b/sys/modules/ext2fs/Makefile
index b746452..2cd0b07 100644
--- a/sys/modules/ext2fs/Makefile
+++ b/sys/modules/ext2fs/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../gnu/ext2fs
KMOD= ext2fs
SRCS= opt_ddb.h opt_quota.h opt_suiddir.h vnode_if.h \
- ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_ihash.c ext2_inode.c \
+ ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_inode.c \
ext2_inode_cnv.c ext2_linux_balloc.c ext2_linux_ialloc.c \
ext2_lookup.c ext2_subr.c ext2_vfsops.c ext2_vnops.c
OpenPOWER on IntegriCloud