- * Allocate a new inode.
- *
- * 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.
- */
-getnewino(dev, ino, ipp)
- dev_t dev;
- ino_t ino;
- struct inode **ipp;
-{
- union ihead *ih;
- register struct inode *ip, *iq;
- register struct vnode *vp;
-
- /*
- * Remove the next inode from the free list.
- */
- if ((ip = ifreeh) == NULL) {
- tablefull("inode");
- *ipp = 0;
- return(ENFILE);
- }
- vp = ITOV(ip);
- if (vp->v_count)
- panic("free inode isn't");
- if (iq = ip->i_freef)
- iq->i_freeb = &ifreeh;
- ifreeh = iq;
- ip->i_freef = NULL;
- ip->i_freeb = NULL;
- /*
- * Now to take inode off the hash chain it was on
- * (initially, or after an iflush, it is on a "hash chain"
- * consisting entirely of itself, and pointed to by no-one)
- * and put it on the chain for its new (ino, dev) pair.
- */
- remque(ip);
- ip->i_dev = dev;
- ip->i_number = ino;
- if (dev != NODEV) {
- ih = &ihead[INOHASH(dev, ino)];
- insque(ip, ih);
- }
- ip->i_flag = 0;
- ILOCK(ip);
- ip->i_lastr = 0;
-#endif SECSIZE
- /*
- * Purge old data structures associated with the inode.
- */
- cache_purge(vp);
- if (ip->i_devvp) {
- vrele(ip->i_devvp);
- ip->i_devvp = 0;
- }
-#ifdef QUOTA
- dqrele(ip->i_dquot);
- ip->i_dquot = NODQUOT;
-#endif
- if (vp->v_type == VBLK) {
- if (bdevlisth == ip) {
- bdevlisth = ip->i_devlst;
- } else {
- for (iq = bdevlisth; iq; iq = iq->i_devlst) {
- if (iq->i_devlst != ip)
- continue;
- iq->i_devlst = ip->i_devlst;
- break;
- }
- if (iq == NULL)
- panic("missing bdev");
- }
- }
- *ipp = ip;
- return (0);
-}
-
-/*
- * Convert a pointer to an inode into a reference to an inode.
- *
- * This is basically the internal piece of iget (after the
- * inode pointer is located) but without the test for mounted
- * filesystems. It is caller's responsibility to check that
- * the inode pointer is valid.
- */
-igrab(ip)
- register struct inode *ip;
-{
- register struct vnode *vp = ITOV(ip);
-
- while ((ip->i_flag&ILOCKED) != 0) {
- ip->i_flag |= IWANT;
- sleep((caddr_t)ip, PINOD);
- }
- if (vp->v_count == 0) { /* ino on free list */
- register struct inode *iq;
-
- if (iq = ip->i_freef)
- iq->i_freeb = ip->i_freeb;
- else
- ifreet = ip->i_freeb;
- *ip->i_freeb = iq;
- ip->i_freef = NULL;
- ip->i_freeb = NULL;
- }
- VREF(vp);
- ILOCK(ip);
-}
-
-/*
- * Create a vnode for a block device.
- * Used for root filesystem, argdev, and swap areas.
- */
-bdevvp(dev, vpp)
- dev_t dev;
- struct vnode **vpp;
-{
- register struct inode *ip;
- register struct vnode *vp;
- struct inode *nip;
- int error;
-
- /*
- * Check for the existence of an existing vnode.
- */
-again:
- for (ip = bdevlisth; ip; ip = ip->i_devlst) {
- vp = ITOV(ip);
- if (dev != vp->v_rdev)
- continue;
- igrab(ip);
- if (dev != vp->v_rdev) {
- iput(ip);
- goto again;
- }
- IUNLOCK(ip);
- *vpp = vp;
- return (0);
- }
- if (error = getnewino(NODEV, (ino_t)0, &nip)) {
- *vpp = 0;
- return (error);
- }
- ip = nip;
- ip->i_fs = 0;
- ip->i_devlst = bdevlisth;
- bdevlisth = ip;
- vp = ITOV(ip);
- vinit(vp, 0, VBLK, &blk_vnodeops);
- vp->v_rdev = dev;
- IUNLOCK(ip);
- *vpp = vp;
- return (0);
-}
-
-/*
- * Decrement reference count of
- * an inode structure.
- * On the last reference,
- * write the inode out and if necessary,
- * truncate and deallocate the file.