xref: /netbsd-src/sys/fs/ntfs/ntfs_ihash.c (revision 14c9669847f16225ecd8967d977ffad240a620ca)
1*14c96698Smaxv /*	$NetBSD: ntfs_ihash.c,v 1.11 2015/02/20 17:08:13 maxv Exp $	*/
29accf4dfSjdolecek 
39accf4dfSjdolecek /*
49accf4dfSjdolecek  * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
59accf4dfSjdolecek  *	The Regents of the University of California.  All rights reserved.
69accf4dfSjdolecek  *
79accf4dfSjdolecek  * Redistribution and use in source and binary forms, with or without
89accf4dfSjdolecek  * modification, are permitted provided that the following conditions
99accf4dfSjdolecek  * are met:
109accf4dfSjdolecek  * 1. Redistributions of source code must retain the above copyright
119accf4dfSjdolecek  *    notice, this list of conditions and the following disclaimer.
129accf4dfSjdolecek  * 2. Redistributions in binary form must reproduce the above copyright
139accf4dfSjdolecek  *    notice, this list of conditions and the following disclaimer in the
149accf4dfSjdolecek  *    documentation and/or other materials provided with the distribution.
15aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
169accf4dfSjdolecek  *    may be used to endorse or promote products derived from this software
179accf4dfSjdolecek  *    without specific prior written permission.
189accf4dfSjdolecek  *
199accf4dfSjdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209accf4dfSjdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219accf4dfSjdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229accf4dfSjdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239accf4dfSjdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249accf4dfSjdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259accf4dfSjdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269accf4dfSjdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279accf4dfSjdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289accf4dfSjdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299accf4dfSjdolecek  * SUCH DAMAGE.
309accf4dfSjdolecek  *
319accf4dfSjdolecek  *	@(#)ufs_ihash.c	8.7 (Berkeley) 5/17/95
329accf4dfSjdolecek  * Id: ntfs_ihash.c,v 1.5 1999/05/12 09:42:58 semenu Exp
339accf4dfSjdolecek  */
349accf4dfSjdolecek 
359accf4dfSjdolecek #include <sys/cdefs.h>
36*14c96698Smaxv __KERNEL_RCSID(0, "$NetBSD: ntfs_ihash.c,v 1.11 2015/02/20 17:08:13 maxv Exp $");
379accf4dfSjdolecek 
389accf4dfSjdolecek #include <sys/param.h>
399accf4dfSjdolecek #include <sys/systm.h>
409accf4dfSjdolecek #include <sys/kernel.h>
419accf4dfSjdolecek #include <sys/lock.h>
429accf4dfSjdolecek #include <sys/vnode.h>
439accf4dfSjdolecek #include <sys/mount.h>
44e62ee4d4Spara #include <sys/mallocvar.h>
459accf4dfSjdolecek 
469accf4dfSjdolecek #include <fs/ntfs/ntfs.h>
479accf4dfSjdolecek #include <fs/ntfs/ntfs_inode.h>
489accf4dfSjdolecek #include <fs/ntfs/ntfs_ihash.h>
499accf4dfSjdolecek 
509accf4dfSjdolecek /*
519accf4dfSjdolecek  * Structures associated with inode cacheing.
529accf4dfSjdolecek  */
539accf4dfSjdolecek static LIST_HEAD(nthashhead, ntnode) *ntfs_nthashtbl;
549accf4dfSjdolecek static u_long	ntfs_nthash;		/* size of hash table - 1 */
559accf4dfSjdolecek #define	NTNOHASH(device, inum)	((minor(device) + (inum)) & ntfs_nthash)
569abeea58Sad static kmutex_t ntfs_nthash_lock;
579abeea58Sad kmutex_t ntfs_hashlock;
589accf4dfSjdolecek 
599accf4dfSjdolecek /*
609accf4dfSjdolecek  * Initialize inode hash table.
619accf4dfSjdolecek  */
629accf4dfSjdolecek void
ntfs_nthashinit(void)63b8817e4aScegger ntfs_nthashinit(void)
649accf4dfSjdolecek {
659abeea58Sad 	mutex_init(&ntfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
669abeea58Sad 	mutex_init(&ntfs_nthash_lock, MUTEX_DEFAULT, IPL_NONE);
67e071d39cSad 	ntfs_nthashtbl = hashinit(desiredvnodes, HASH_LIST, true, &ntfs_nthash);
689accf4dfSjdolecek }
699accf4dfSjdolecek 
709accf4dfSjdolecek /*
719accf4dfSjdolecek  * Reinitialize inode hash table.
729accf4dfSjdolecek  */
739accf4dfSjdolecek 
749accf4dfSjdolecek void
ntfs_nthashreinit(void)75b8817e4aScegger ntfs_nthashreinit(void)
769accf4dfSjdolecek {
779accf4dfSjdolecek 	struct ntnode *ip;
789accf4dfSjdolecek 	struct nthashhead *oldhash, *hash;
799accf4dfSjdolecek 	u_long oldmask, mask, val;
809accf4dfSjdolecek 	int i;
819accf4dfSjdolecek 
82e071d39cSad 	hash = hashinit(desiredvnodes, HASH_LIST, true, &mask);
839accf4dfSjdolecek 
849abeea58Sad 	mutex_enter(&ntfs_nthash_lock);
859accf4dfSjdolecek 	oldhash = ntfs_nthashtbl;
869accf4dfSjdolecek 	oldmask = ntfs_nthash;
879accf4dfSjdolecek 	ntfs_nthashtbl = hash;
889accf4dfSjdolecek 	ntfs_nthash = mask;
899accf4dfSjdolecek 	for (i = 0; i <= oldmask; i++) {
909accf4dfSjdolecek 		while ((ip = LIST_FIRST(&oldhash[i])) != NULL) {
919accf4dfSjdolecek 			LIST_REMOVE(ip, i_hash);
929accf4dfSjdolecek 			val = NTNOHASH(ip->i_dev, ip->i_number);
939accf4dfSjdolecek 			LIST_INSERT_HEAD(&hash[val], ip, i_hash);
949accf4dfSjdolecek 		}
959accf4dfSjdolecek 	}
969abeea58Sad 	mutex_exit(&ntfs_nthash_lock);
97e071d39cSad 	hashdone(oldhash, HASH_LIST, oldmask);
989accf4dfSjdolecek }
999accf4dfSjdolecek 
1009accf4dfSjdolecek /*
1019accf4dfSjdolecek  * Free the inode hash table. Called from ntfs_done(), only needed
1029accf4dfSjdolecek  * on NetBSD.
1039accf4dfSjdolecek  */
1049accf4dfSjdolecek void
ntfs_nthashdone(void)105b8817e4aScegger ntfs_nthashdone(void)
1069accf4dfSjdolecek {
107e071d39cSad 	hashdone(ntfs_nthashtbl, HASH_LIST, ntfs_nthash);
108b89010bfSad 	mutex_destroy(&ntfs_hashlock);
109b89010bfSad 	mutex_destroy(&ntfs_nthash_lock);
1109accf4dfSjdolecek }
1119accf4dfSjdolecek 
1129accf4dfSjdolecek /*
1139accf4dfSjdolecek  * Use the device/inum pair to find the incore inode, and return a pointer
1149accf4dfSjdolecek  * to it. If it is in core, return it, even if it is locked.
1159accf4dfSjdolecek  */
1169accf4dfSjdolecek struct ntnode *
ntfs_nthashlookup(dev_t dev,ino_t inum)117454af1c0Sdsl ntfs_nthashlookup(dev_t dev, ino_t inum)
1189accf4dfSjdolecek {
1199accf4dfSjdolecek 	struct ntnode *ip;
1209accf4dfSjdolecek 	struct nthashhead *ipp;
1219accf4dfSjdolecek 
1229abeea58Sad 	mutex_enter(&ntfs_nthash_lock);
1239accf4dfSjdolecek 	ipp = &ntfs_nthashtbl[NTNOHASH(dev, inum)];
1249accf4dfSjdolecek 	LIST_FOREACH(ip, ipp, i_hash) {
1259accf4dfSjdolecek 		if (inum == ip->i_number && dev == ip->i_dev)
1269accf4dfSjdolecek 			break;
1279accf4dfSjdolecek 	}
1289abeea58Sad 	mutex_exit(&ntfs_nthash_lock);
1299accf4dfSjdolecek 
1309accf4dfSjdolecek 	return (ip);
1319accf4dfSjdolecek }
1329accf4dfSjdolecek 
1339accf4dfSjdolecek /*
1349accf4dfSjdolecek  * Insert the ntnode into the hash table.
1359accf4dfSjdolecek  */
1369accf4dfSjdolecek void
ntfs_nthashins(struct ntnode * ip)137454af1c0Sdsl ntfs_nthashins(struct ntnode *ip)
1389accf4dfSjdolecek {
1399accf4dfSjdolecek 	struct nthashhead *ipp;
1409accf4dfSjdolecek 
1419abeea58Sad 	mutex_enter(&ntfs_nthash_lock);
1429accf4dfSjdolecek 	ipp = &ntfs_nthashtbl[NTNOHASH(ip->i_dev, ip->i_number)];
1439accf4dfSjdolecek 	LIST_INSERT_HEAD(ipp, ip, i_hash);
1449accf4dfSjdolecek 	ip->i_flag |= IN_HASHED;
1459abeea58Sad 	mutex_exit(&ntfs_nthash_lock);
1469accf4dfSjdolecek }
1479accf4dfSjdolecek 
1489accf4dfSjdolecek /*
1499accf4dfSjdolecek  * Remove the inode from the hash table.
1509accf4dfSjdolecek  */
1519accf4dfSjdolecek void
ntfs_nthashrem(struct ntnode * ip)152454af1c0Sdsl ntfs_nthashrem(struct ntnode *ip)
1539accf4dfSjdolecek {
1549abeea58Sad 	mutex_enter(&ntfs_nthash_lock);
1559accf4dfSjdolecek 	if (ip->i_flag & IN_HASHED) {
1569accf4dfSjdolecek 		ip->i_flag &= ~IN_HASHED;
1579accf4dfSjdolecek 		LIST_REMOVE(ip, i_hash);
1589accf4dfSjdolecek 	}
1599abeea58Sad 	mutex_exit(&ntfs_nthash_lock);
1609accf4dfSjdolecek }
161