151517Sbostic /*
263376Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1993
363376Sbostic * The Regents of the University of California. All rights reserved.
451517Sbostic *
551517Sbostic * %sccs.include.redist.c%
651517Sbostic *
7*65234Smckusick * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93
851517Sbostic */
951517Sbostic
1051517Sbostic #include <sys/param.h>
1151517Sbostic #include <sys/systm.h>
1251517Sbostic #include <sys/vnode.h>
1351975Smckusick #include <sys/malloc.h>
1457037Smckusick #include <sys/proc.h>
1551517Sbostic
1651517Sbostic #include <ufs/ufs/quota.h>
1751517Sbostic #include <ufs/ufs/inode.h>
1851517Sbostic #include <ufs/ufs/ufs_extern.h>
1951517Sbostic
2051975Smckusick /*
2151975Smckusick * Structures associated with inode cacheing.
2251975Smckusick */
2355411Smckusick struct inode **ihashtbl;
2455411Smckusick u_long ihash; /* size of hash table - 1 */
2564427Sbostic #define INOHASH(device, inum) (((device) + (inum)) & ihash)
2651517Sbostic
2751517Sbostic /*
2851517Sbostic * Initialize inode hash table.
2951517Sbostic */
3051517Sbostic void
ufs_ihashinit()3151517Sbostic ufs_ihashinit()
3251517Sbostic {
3351517Sbostic
3455411Smckusick ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash);
3551517Sbostic }
3651517Sbostic
3751517Sbostic /*
3864427Sbostic * Use the device/inum pair to find the incore inode, and return a pointer
3964427Sbostic * to it. If it is in core, return it, even if it is locked.
4057038Smargo */
4157038Smargo struct vnode *
ufs_ihashlookup(device,inum)4264427Sbostic ufs_ihashlookup(device, inum)
4364427Sbostic dev_t device;
4464427Sbostic ino_t inum;
4557038Smargo {
4664601Sbostic register struct inode *ip;
4757038Smargo
4864601Sbostic for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
4964601Sbostic if (ip == NULL)
5064601Sbostic return (NULL);
5164427Sbostic if (inum == ip->i_number && device == ip->i_dev)
5264427Sbostic return (ITOV(ip));
5364601Sbostic }
5464601Sbostic /* NOTREACHED */
5557038Smargo }
5657038Smargo
5757038Smargo /*
5864427Sbostic * Use the device/inum pair to find the incore inode, and return a pointer
5964427Sbostic * to it. If it is in core, but locked, wait for it.
6051517Sbostic */
6151553Smckusick struct vnode *
ufs_ihashget(device,inum)6264427Sbostic ufs_ihashget(device, inum)
6364427Sbostic dev_t device;
6464427Sbostic ino_t inum;
6551517Sbostic {
6664601Sbostic register struct inode *ip;
6751553Smckusick struct vnode *vp;
6851517Sbostic
6964601Sbostic for (;;)
7064601Sbostic for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
7164601Sbostic if (ip == NULL)
7264601Sbostic return (NULL);
7364601Sbostic if (inum == ip->i_number && device == ip->i_dev) {
7464601Sbostic if (ip->i_flag & IN_LOCKED) {
7564601Sbostic ip->i_flag |= IN_WANTED;
7664601Sbostic sleep(ip, PINOD);
7764601Sbostic break;
7864601Sbostic }
7964601Sbostic vp = ITOV(ip);
80*65234Smckusick if (!vget(vp, 1))
8164601Sbostic return (vp);
8264601Sbostic break;
8364427Sbostic }
8451517Sbostic }
8564601Sbostic /* NOTREACHED */
8651517Sbostic }
8751517Sbostic
8851517Sbostic /*
8951517Sbostic * Insert the inode into the hash table, and return it locked.
9051517Sbostic */
9151517Sbostic void
ufs_ihashins(ip)9251517Sbostic ufs_ihashins(ip)
9351517Sbostic struct inode *ip;
9451517Sbostic {
9555411Smckusick struct inode **ipp, *iq;
9655411Smckusick
9755411Smckusick ipp = &ihashtbl[INOHASH(ip->i_dev, ip->i_number)];
9855411Smckusick if (iq = *ipp)
9955411Smckusick iq->i_prev = &ip->i_next;
10055411Smckusick ip->i_next = iq;
10155411Smckusick ip->i_prev = ipp;
10255411Smckusick *ipp = ip;
10364601Sbostic if (ip->i_flag & IN_LOCKED)
10456801Smckusick panic("ufs_ihashins: already locked");
10557037Smckusick if (curproc)
10657037Smckusick ip->i_lockholder = curproc->p_pid;
10757037Smckusick else
10857037Smckusick ip->i_lockholder = -1;
10964601Sbostic ip->i_flag |= IN_LOCKED;
11051517Sbostic }
11155411Smckusick
11255411Smckusick /*
11355411Smckusick * Remove the inode from the hash table.
11455411Smckusick */
11555411Smckusick void
ufs_ihashrem(ip)11655411Smckusick ufs_ihashrem(ip)
11755411Smckusick register struct inode *ip;
11855411Smckusick {
11955411Smckusick register struct inode *iq;
12055411Smckusick
12155411Smckusick if (iq = ip->i_next)
12255411Smckusick iq->i_prev = ip->i_prev;
12355411Smckusick *ip->i_prev = iq;
12455411Smckusick #ifdef DIAGNOSTIC
12555411Smckusick ip->i_next = NULL;
12655411Smckusick ip->i_prev = NULL;
12755411Smckusick #endif
12855411Smckusick }
129