summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_hash.c')
-rw-r--r--sys/kern/vfs_hash.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/sys/kern/vfs_hash.c b/sys/kern/vfs_hash.c
index 0271e49..1398a47 100644
--- a/sys/kern/vfs_hash.c
+++ b/sys/kern/vfs_hash.c
@@ -160,3 +160,40 @@ vfs_hash_rehash(struct vnode *vp, u_int hash)
vp->v_hash = hash;
mtx_unlock(&vfs_hash_mtx);
}
+
+void
+vfs_hash_changesize(int newmaxvnodes)
+{
+ struct vfs_hash_head *vfs_hash_newtbl, *vfs_hash_oldtbl;
+ u_long vfs_hash_newmask, vfs_hash_oldmask;
+ struct vnode *vp;
+ int i;
+
+ vfs_hash_newtbl = hashinit(newmaxvnodes, M_VFS_HASH,
+ &vfs_hash_newmask);
+ /* If same hash table size, nothing to do */
+ if (vfs_hash_mask == vfs_hash_newmask) {
+ free(vfs_hash_newtbl, M_VFS_HASH);
+ return;
+ }
+ /*
+ * Move everything from the old hash table to the new table.
+ * None of the vnodes in the table can be recycled because to
+ * do so, they have to be removed from the hash table.
+ */
+ rw_wlock(&vfs_hash_lock);
+ vfs_hash_oldtbl = vfs_hash_tbl;
+ vfs_hash_oldmask = vfs_hash_mask;
+ vfs_hash_tbl = vfs_hash_newtbl;
+ vfs_hash_mask = vfs_hash_newmask;
+ for (i = 0; i <= vfs_hash_oldmask; i++) {
+ while ((vp = LIST_FIRST(&vfs_hash_oldtbl[i])) != NULL) {
+ LIST_REMOVE(vp, v_hashlist);
+ LIST_INSERT_HEAD(
+ vfs_hash_bucket(vp->v_mount, vp->v_hash),
+ vp, v_hashlist);
+ }
+ }
+ rw_wunlock(&vfs_hash_lock);
+ free(vfs_hash_oldtbl, M_VFS_HASH);
+}
OpenPOWER on IntegriCloud