1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_alloc.c 7.29 (Berkeley) 09/25/91 8 */ 9 10 #include "param.h" 11 #include "kernel.h" 12 #include "buf.h" 13 #include "vnode.h" 14 #include "syslog.h" 15 #include "../ufs/quota.h" 16 #include "../ufs/inode.h" 17 #include "mount.h" 18 #include "../ufs/ufsmount.h" 19 #include "lfs.h" 20 #include "lfs_extern.h" 21 22 #define LFS_IENTRY(I, F, IN, BP) \ 23 if (bread((F)->lfs_ivnode, (IN) / IFPB(F) + (F)->lfs_segtabsz, \ 24 (F)->lfs_bsize, NOCRED, &BP)) \ 25 panic("ifile read"); \ 26 (I) = (IFILE *)BP->b_un.b_addr + IN % IFPB(F); 27 28 ino_t 29 lfs_ialloc(fs, pip, ipp, cred) 30 LFS *fs; 31 INODE *pip, **ipp; 32 UCRED *cred; 33 { 34 BUF *bp; 35 IFILE *ifp; 36 INODE *ip; 37 VNODE *vp; 38 ino_t new_ino; 39 int error; 40 41 new_ino = fs->lfs_free; 42 printf("lfs_ialloc: next free %d\n", new_ino); 43 if (new_ino == LFS_UNUSED_INUM) { /* XXX -- allocate more */ 44 uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt); 45 log(LOG_ERR, "uid %d on %s: out of inodes\n", 46 cred->cr_uid, fs->lfs_fsmnt); 47 return (ENOSPC); 48 } 49 50 /* Read the appropriate block from the ifile */ 51 vp = fs->lfs_ivnode; 52 LFS_IENTRY(ifp, fs, new_ino, bp); 53 54 if (ifp->if_daddr != LFS_UNUSED_DADDR) 55 panic("lfs_ialloc: corrupt free list"); 56 57 /* Remove from free list, set the access time. */ 58 fs->lfs_free = ifp->if_nextfree; 59 ifp->if_st_atime = time.tv_sec; 60 brelse(bp); 61 62 error = lfs_vcreate(ITOV(pip)->v_mount, new_ino, &vp); 63 if (error) 64 return (error); 65 66 ip = VTOI(vp); 67 VREF(ip->i_devvp); 68 69 /* 70 * Set up a new generation number for this inode. 71 */ 72 if (++nextgennumber < (u_long)time.tv_sec) 73 nextgennumber = time.tv_sec; 74 ip->i_gen = nextgennumber; 75 76 lfs_hqueue(ip); 77 78 *ipp = ip; 79 return (0); 80 } 81 82 void 83 lfs_ifree(ip) 84 INODE *ip; 85 { 86 BUF *bp; 87 IFILE *ifp; 88 LFS *fs; 89 ino_t ino; 90 91 printf("lfs_ifree: free %d\n", ip->i_number); 92 fs = ip->i_lfs; 93 ino = ip->i_number; 94 LFS_IENTRY(ifp, fs, ino, bp); 95 96 ifp->if_daddr = LFS_UNUSED_DADDR; 97 ++ifp->if_version; 98 ifp->if_nextfree = fs->lfs_free; 99 brelse(bp); 100 fs->lfs_free = ino; 101 fs->lfs_fmod = 1; 102 } 103 104 daddr_t 105 itod(fs, ino) 106 LFS *fs; 107 ino_t ino; 108 { 109 BUF *bp; 110 IFILE *ifp; 111 daddr_t iaddr; 112 113 printf("itod: ino %d\n", ino); 114 LFS_IENTRY(ifp, fs, ino, bp); 115 116 if (ifp->if_daddr == LFS_UNUSED_DADDR) 117 panic("itod: unused daddr"); 118 iaddr = ifp->if_daddr; 119 brelse(bp); 120 return (iaddr); 121 } 122 123 DINODE * 124 lfs_ifind(fs, ino, page) 125 LFS *fs; 126 ino_t ino; 127 void *page; 128 { 129 register DINODE *dip; 130 register int cnt; 131 132 printf("lfs_ifind: inode %d\n", ino); 133 dip = page; 134 for (cnt = INOPB(fs); cnt--; ++dip) 135 if (dip->di_inum == ino) 136 return (dip); 137 138 (void)printf("lfs_ifind: dinode %u not found", ino); 139 panic("lfs_ifind: inode not found"); 140 /* NOTREACHED */ 141 } 142 143 /* 144 * Create a new vnode/inode and initialize the fields we can. 145 */ 146 lfs_vcreate(mp, ino, vpp) 147 MOUNT *mp; 148 ino_t ino; 149 VNODE **vpp; 150 { 151 INODE *ip; 152 UFSMOUNT *ump; 153 int error, i; 154 155 printf("lfs_vcreate: ino %d\n", ino); 156 error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp); 157 if (error) 158 return(error); 159 160 ump = VFSTOUFS(mp); 161 162 /* Initialize the inode. */ 163 ip = VTOI(*vpp); 164 ip->i_diroff = 0; 165 ip->i_devvp = ump->um_devvp; 166 ip->i_dev = ump->um_dev; 167 ip->i_flag = 0; 168 ip->i_lfs = ump->um_lfs; 169 ip->i_lockf = 0; 170 ip->i_mode = 0; 171 ip->i_number = ip->i_din.di_inum = ino; 172 ip->i_vnode = *vpp; 173 #ifdef QUOTA 174 for (i = 0; i < MAXQUOTAS; i++) 175 ip->i_dquot[i] = NODQUOT; 176 #endif 177 return (0); 178 } 179 180 /* 181 * Return the current version number for a specific inode. 182 */ 183 u_long 184 lfs_getversion(fs, ino) 185 LFS *fs; 186 ino_t ino; 187 { 188 IFILE *ifp; 189 BUF *bp; 190 int version; 191 192 printf("lfs_getversion: %d\n", ino); 193 LFS_IENTRY(ifp, fs, ino, bp); 194 version = ifp->if_version; 195 brelse(bp); 196 return(version); 197 } 198