X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/5e1f692795138f170b828b8305c99027a17372aa..a18538c92b3fbcaa835cae4bc38a5b50faa13519:/usr/src/sys/ufs/lfs/lfs_alloc.c diff --git a/usr/src/sys/ufs/lfs/lfs_alloc.c b/usr/src/sys/ufs/lfs/lfs_alloc.c index fadfee4c3b..96bd309be1 100644 --- a/usr/src/sys/ufs/lfs/lfs_alloc.c +++ b/usr/src/sys/ufs/lfs/lfs_alloc.c @@ -1,79 +1,109 @@ /* - * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * Copyright (c) 1991 Regents of the University of California. * All rights reserved. * * %sccs.include.redist.c% * - * @(#)lfs_alloc.c 7.31 (Berkeley) %G% + * @(#)lfs_alloc.c 7.54 (Berkeley) %G% */ -#ifdef LOGFS -#include "param.h" -#include "kernel.h" -#include "buf.h" -#include "vnode.h" -#include "syslog.h" -#include "mount.h" -#include "../ufs/quota.h" -#include "../ufs/inode.h" -#include "../ufs/ufsmount.h" -#include "lfs.h" -#include "lfs_extern.h" - -/* Read in the block containing a specific inode from the ifile. */ -#define LFS_IENTRY(I, F, IN, BP) \ - if (bread((F)->lfs_ivnode, (IN) / IFPB(F) + (F)->lfs_segtabsz, \ - (F)->lfs_bsize, NOCRED, &BP)) \ - panic("lfs_ientry: read"); \ - (I) = (IFILE *)BP->b_un.b_addr + IN % IFPB(F); - -/* - * Allocate a new inode. - */ -ino_t -lfs_ialloc(fs, pip, ipp, cred) - LFS *fs; - INODE *pip, **ipp; - UCRED *cred; +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +extern u_long nextgennumber; + +/* Allocate a new inode. */ +/* ARGSUSED */ +int +lfs_valloc(ap) + struct vop_valloc_args /* { + struct vnode *a_pvp; + int a_mode; + struct ucred *a_cred; + struct vnode **a_vpp; + } */ *ap; { - BUF *bp; - IFILE *ifp; - INODE *ip; - VNODE *vp; + struct lfs *fs; + struct buf *bp; + struct ifile *ifp; + struct inode *ip; + struct vnode *vp; + daddr_t blkno; ino_t new_ino; - int error; + u_long i, max; + int bb, error; /* Get the head of the freelist. */ + fs = VTOI(ap->a_pvp)->i_lfs; new_ino = fs->lfs_free; - if (new_ino == LFS_UNUSED_INUM) { - /* - * XXX - * Currently, no more inodes are allocated if the ifile fills - * up. The ifile should be extended instead. - */ - uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt); - log(LOG_ERR, "uid %d on %s: out of inodes\n", - cred->cr_uid, fs->lfs_fsmnt); - return (ENOSPC); - } -printf("lfs_ialloc: allocate inode %d\n", new_ino); +#ifdef ALLOCPRINT + printf("lfs_ialloc: allocate inode %d\n", new_ino); +#endif - /* Read the appropriate block from the ifile. */ + /* + * Remove the inode from the free list and write the new start + * of the free list into the superblock. + */ LFS_IENTRY(ifp, fs, new_ino, bp); - if (ifp->if_daddr != LFS_UNUSED_DADDR) panic("lfs_ialloc: inuse inode on the free list"); - - /* Remove from the free list, set the access time, write it back. */ fs->lfs_free = ifp->if_nextfree; - ifp->if_st_atime = time.tv_sec; - lfs_bwrite(bp); + brelse(bp); + + /* Extend IFILE so that the next lfs_valloc will succeed. */ + if (fs->lfs_free == LFS_UNUSED_INUM) { + bb = fsbtodb(fs, 1); + if (!ISSPACE(fs, bb, ap->a_cred)) + return(ENOSPC); + vp = fs->lfs_ivnode; + ip = VTOI(vp); + blkno = lblkno(fs, ip->i_size); + bp = getblk(vp, blkno, fs->lfs_bsize); + i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) * + fs->lfs_ifpb; + fs->lfs_free = i; + max = i + fs->lfs_ifpb; + for (ifp = (struct ifile *)bp->b_un.b_words; i < max; ++ifp) { + ifp->if_version = 1; + ifp->if_daddr = LFS_UNUSED_DADDR; + ifp->if_nextfree = ++i; + } + ifp--; + ifp->if_nextfree = LFS_UNUSED_INUM; + + ip->i_blocks += btodb(fs->lfs_bsize); + fs->lfs_bfree -= btodb(fs->lfs_bsize); + ip->i_size += fs->lfs_bsize; + vnode_pager_setsize(vp, (u_long)ip->i_size); + vnode_pager_uncache(vp); + if (error = VOP_BWRITE(bp)) + return (error); + } /* Create a vnode to associate with the inode. */ - error = lfs_vcreate(ITOV(pip)->v_mount, new_ino, &vp); - if (error) + if (error = lfs_vcreate(ap->a_pvp->v_mount, new_ino, &vp)) return (error); - *ipp = ip = VTOI(vp); + *ap->a_vpp = vp; + vp->v_flag |= VDIROP; + ip = VTOI(vp); + VREF(ip->i_devvp); + + /* Zero out the direct and indirect block addresses. */ + bzero(ip->i_db, (NDADDR + NIADDR) * sizeof(daddr_t)); /* Set a new generation number for this inode. */ if (++nextgennumber < (u_long)time.tv_sec) @@ -81,7 +111,7 @@ printf("lfs_ialloc: allocate inode %d\n", new_ino); ip->i_gen = nextgennumber; /* Insert into the inode hash table. */ - lfs_hqueue(ip); + ufs_ihashins(ip); /* Set superblock modified bit and increment file count. */ fs->lfs_fmod = 1; @@ -89,156 +119,101 @@ printf("lfs_ialloc: allocate inode %d\n", new_ino); return (0); } -/* Free an inode. */ -void -lfs_ifree(ip) - INODE *ip; -{ - BUF *bp; - IFILE *ifp; - LFS *fs; - ino_t ino; - -printf("lfs_ifree: free %d\n", ip->i_number); - /* Get the inode number and file system. */ - fs = ip->i_lfs; - ino = ip->i_number; - - /* - * Read the appropriate block from the ifile. Set the inode entry to - * unused, increment its version number and link it into the free chain. - */ - LFS_IENTRY(ifp, fs, ino, bp); - ifp->if_daddr = LFS_UNUSED_DADDR; - ++ifp->if_version; - ifp->if_nextfree = fs->lfs_free; - fs->lfs_free = ino; - - lfs_bwrite(bp); - - /* Set superblock modified bit and decrement file count. */ - fs->lfs_fmod = 1; - --fs->lfs_nfiles; -} - -/* Translate an inode number to a disk address. */ -daddr_t -itod(fs, ino) - LFS *fs; - ino_t ino; -{ - BUF *bp; - IFILE *ifp; - daddr_t iaddr; - - /* Read the appropriate block from the ifile. */ - LFS_IENTRY(ifp, fs, ino, bp); - - if (ifp->if_daddr == LFS_UNUSED_DADDR) - panic("itod: unused disk address"); - iaddr = ifp->if_daddr; - brelse(bp); - return (iaddr); -} - -/* Search a block for a specific dinode. */ -DINODE * -lfs_ifind(fs, ino, page) - LFS *fs; - ino_t ino; - void *page; -{ - register DINODE *dip; - register int cnt; - -printf("lfs_ifind: inode %d\n", ino); - dip = page; - for (cnt = INOPB(fs); cnt--; ++dip) - if (dip->di_inum == ino) - return (dip); - - panic("lfs_ifind: dinode %%u not found", ino); - /* NOTREACHED */ -} - /* Create a new vnode/inode pair and initialize what fields we can. */ +int lfs_vcreate(mp, ino, vpp) - MOUNT *mp; + struct mount *mp; ino_t ino; - VNODE **vpp; + struct vnode **vpp; { - INODE *ip; - UFSMOUNT *ump; + extern int (**lfs_vnodeop_p)(); + struct inode *ip; + struct ufsmount *ump; int error, i; -printf("lfs_vcreate: ino %d\n", ino); /* Create the vnode. */ - if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp)) + if (error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, vpp)) { + *vpp = NULL; return (error); + } /* Get a pointer to the private mount structure. */ ump = VFSTOUFS(mp); /* Initialize the inode. */ - ip = VTOI(*vpp); - ip->i_diroff = 0; + MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK); + (*vpp)->v_data = ip; + ip->i_vnode = *vpp; ip->i_devvp = ump->um_devvp; + ip->i_flag = IMOD; ip->i_dev = ump->um_dev; - ip->i_flag = 0; - ip->i_lfs = ump->um_lfs; - ip->i_lockf = 0; - ip->i_mode = 0; ip->i_number = ip->i_din.di_inum = ino; - ip->i_vnode = *vpp; + ip->i_lfs = ump->um_lfs; #ifdef QUOTA for (i = 0; i < MAXQUOTAS; i++) ip->i_dquot[i] = NODQUOT; #endif - VREF(ip->i_devvp); /* XXX: Why? */ + ip->i_lockf = 0; + ip->i_diroff = 0; + ip->i_mode = 0; + ip->i_size = 0; + ip->i_blocks = 0; + ++ump->um_lfs->lfs_uinodes; return (0); } -/* Return the current version number for a specific inode. */ -u_long -lfs_getversion(fs, ino) - LFS *fs; - ino_t ino; -{ - BUF *bp; - IFILE *ifp; - u_long version; - - /* - * Read the appropriate block from the ifile. Return the - * version number. - */ - LFS_IENTRY(ifp, fs, ino, bp); - version = ifp->if_version; - brelse(bp); - return (version); -} - -/* Set values in the ifile for the inode. */ -void -lfs_iset(ip, daddr, atime) - INODE *ip; - daddr_t daddr; - time_t atime; +/* Free an inode. */ +/* ARGUSED */ +int +lfs_vfree(ap) + struct vop_vfree_args /* { + struct vnode *a_pvp; + ino_t a_ino; + int a_mode; + } */ *ap; { - BUF *bp; - IFILE *ifp; - LFS *fs; + SEGUSE *sup; + struct buf *bp; + struct ifile *ifp; + struct inode *ip; + struct lfs *fs; + daddr_t old_iaddr; ino_t ino; + int error; -printf("lfs_iset: setting ino %d daddr %lx time %lx\n", -ip->i_number, daddr, atime); - + /* Get the inode number and file system. */ + ip = VTOI(ap->a_pvp); fs = ip->i_lfs; ino = ip->i_number; + if (ip->i_flag & IMOD) { + --fs->lfs_uinodes; + ip->i_flag &= ~(IMOD | IACC | IUPD | ICHG); + } + /* + * Set the ifile's inode entry to unused, increment its version number + * and link it into the free chain. + */ LFS_IENTRY(ifp, fs, ino, bp); + old_iaddr = ifp->if_daddr; + ifp->if_daddr = LFS_UNUSED_DADDR; + ++ifp->if_version; + ifp->if_nextfree = fs->lfs_free; + fs->lfs_free = ino; + (void) VOP_BWRITE(bp); + + if (old_iaddr != LFS_UNUSED_DADDR) { + LFS_SEGENTRY(sup, fs, datosn(fs, old_iaddr), bp); +#ifdef DIAGNOSTIC + if (sup->su_nbytes < sizeof(struct dinode)) + panic("lfs_vfree: negative byte count (segment %d)\n", + datosn(fs, old_iaddr)); +#endif + sup->su_nbytes -= sizeof(struct dinode); + (void) VOP_BWRITE(bp); + } - ifp->if_daddr = daddr; - ifp->if_st_atime = atime; - lfs_bwrite(bp); + /* Set superblock modified bit and decrement file count. */ + fs->lfs_fmod = 1; + --fs->lfs_nfiles; + return (0); } -#endif /* LOGFS */