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.30 (Berkeley) 10/02/91 8 */ 9 10 #ifdef LOGFS 11 #include "param.h" 12 #include "kernel.h" 13 #include "buf.h" 14 #include "vnode.h" 15 #include "syslog.h" 16 #include "mount.h" 17 #include "../ufs/quota.h" 18 #include "../ufs/inode.h" 19 #include "../ufs/ufsmount.h" 20 #include "lfs.h" 21 #include "lfs_extern.h" 22 23 /* Read in the block containing a specific inode from the ifile. */ 24 #define LFS_IENTRY(I, F, IN, BP) \ 25 if (bread((F)->lfs_ivnode, (IN) / IFPB(F) + (F)->lfs_segtabsz, \ 26 (F)->lfs_bsize, NOCRED, &BP)) \ 27 panic("lfs_ientry: read"); \ 28 (I) = (IFILE *)BP->b_un.b_addr + IN % IFPB(F); 29 30 /* 31 * Allocate a new inode. 32 */ 33 ino_t 34 lfs_ialloc(fs, pip, ipp, cred) 35 LFS *fs; 36 INODE *pip, **ipp; 37 UCRED *cred; 38 { 39 BUF *bp; 40 IFILE *ifp; 41 INODE *ip; 42 VNODE *vp; 43 ino_t new_ino; 44 int error; 45 46 /* Get the head of the freelist. */ 47 new_ino = fs->lfs_free; 48 if (new_ino == LFS_UNUSED_INUM) { 49 /* 50 * XXX 51 * Currently, no more inodes are allocated if the ifile fills 52 * up. The ifile should be extended instead. 53 */ 54 uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt); 55 log(LOG_ERR, "uid %d on %s: out of inodes\n", 56 cred->cr_uid, fs->lfs_fsmnt); 57 return (ENOSPC); 58 } 59 printf("lfs_ialloc: allocate inode %d\n", new_ino); 60 61 /* Read the appropriate block from the ifile. */ 62 LFS_IENTRY(ifp, fs, new_ino, bp); 63 64 if (ifp->if_daddr != LFS_UNUSED_DADDR) 65 panic("lfs_ialloc: inuse inode on the free list"); 66 67 /* Remove from the free list, set the access time, write it back. */ 68 fs->lfs_free = ifp->if_nextfree; 69 ifp->if_st_atime = time.tv_sec; 70 lfs_bwrite(bp); 71 72 /* Create a vnode to associate with the inode. */ 73 error = lfs_vcreate(ITOV(pip)->v_mount, new_ino, &vp); 74 if (error) 75 return (error); 76 *ipp = ip = VTOI(vp); 77 78 /* Set a new generation number for this inode. */ 79 if (++nextgennumber < (u_long)time.tv_sec) 80 nextgennumber = time.tv_sec; 81 ip->i_gen = nextgennumber; 82 83 /* Insert into the inode hash table. */ 84 lfs_hqueue(ip); 85 86 /* Set superblock modified bit and increment file count. */ 87 fs->lfs_fmod = 1; 88 ++fs->lfs_nfiles; 89 return (0); 90 } 91 92 /* Free an inode. */ 93 void 94 lfs_ifree(ip) 95 INODE *ip; 96 { 97 BUF *bp; 98 IFILE *ifp; 99 LFS *fs; 100 ino_t ino; 101 102 printf("lfs_ifree: free %d\n", ip->i_number); 103 /* Get the inode number and file system. */ 104 fs = ip->i_lfs; 105 ino = ip->i_number; 106 107 /* 108 * Read the appropriate block from the ifile. Set the inode entry to 109 * unused, increment its version number and link it into the free chain. 110 */ 111 LFS_IENTRY(ifp, fs, ino, bp); 112 ifp->if_daddr = LFS_UNUSED_DADDR; 113 ++ifp->if_version; 114 ifp->if_nextfree = fs->lfs_free; 115 fs->lfs_free = ino; 116 117 lfs_bwrite(bp); 118 119 /* Set superblock modified bit and decrement file count. */ 120 fs->lfs_fmod = 1; 121 --fs->lfs_nfiles; 122 } 123 124 /* Translate an inode number to a disk address. */ 125 daddr_t 126 itod(fs, ino) 127 LFS *fs; 128 ino_t ino; 129 { 130 BUF *bp; 131 IFILE *ifp; 132 daddr_t iaddr; 133 134 /* Read the appropriate block from the ifile. */ 135 LFS_IENTRY(ifp, fs, ino, bp); 136 137 if (ifp->if_daddr == LFS_UNUSED_DADDR) 138 panic("itod: unused disk address"); 139 iaddr = ifp->if_daddr; 140 brelse(bp); 141 return (iaddr); 142 } 143 144 /* Search a block for a specific dinode. */ 145 DINODE * 146 lfs_ifind(fs, ino, page) 147 LFS *fs; 148 ino_t ino; 149 void *page; 150 { 151 register DINODE *dip; 152 register int cnt; 153 154 printf("lfs_ifind: inode %d\n", ino); 155 dip = page; 156 for (cnt = INOPB(fs); cnt--; ++dip) 157 if (dip->di_inum == ino) 158 return (dip); 159 160 panic("lfs_ifind: dinode %%u not found", ino); 161 /* NOTREACHED */ 162 } 163 164 /* Create a new vnode/inode pair and initialize what fields we can. */ 165 lfs_vcreate(mp, ino, vpp) 166 MOUNT *mp; 167 ino_t ino; 168 VNODE **vpp; 169 { 170 INODE *ip; 171 UFSMOUNT *ump; 172 int error, i; 173 174 printf("lfs_vcreate: ino %d\n", ino); 175 /* Create the vnode. */ 176 if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp)) 177 return(error); 178 179 /* Get a pointer to the private mount structure. */ 180 ump = VFSTOUFS(mp); 181 182 /* Initialize the inode. */ 183 ip = VTOI(*vpp); 184 ip->i_diroff = 0; 185 ip->i_devvp = ump->um_devvp; 186 ip->i_dev = ump->um_dev; 187 ip->i_flag = 0; 188 ip->i_lfs = ump->um_lfs; 189 ip->i_lockf = 0; 190 ip->i_mode = 0; 191 ip->i_number = ip->i_din.di_inum = ino; 192 ip->i_vnode = *vpp; 193 #ifdef QUOTA 194 for (i = 0; i < MAXQUOTAS; i++) 195 ip->i_dquot[i] = NODQUOT; 196 #endif 197 VREF(ip->i_devvp); /* XXX: Why? */ 198 return (0); 199 } 200 201 /* Return the current version number for a specific inode. */ 202 u_long 203 lfs_getversion(fs, ino) 204 LFS *fs; 205 ino_t ino; 206 { 207 BUF *bp; 208 IFILE *ifp; 209 u_long version; 210 211 /* 212 * Read the appropriate block from the ifile. Return the version 213 * number. 214 */ 215 LFS_IENTRY(ifp, fs, ino, bp); 216 version = ifp->if_version; 217 brelse(bp); 218 return(version); 219 } 220 221 /* Set values in the ifile for the inode. */ 222 void 223 lfs_iset(ip, daddr, atime) 224 INODE *ip; 225 daddr_t daddr; 226 time_t atime; 227 { 228 BUF *bp; 229 IFILE *ifp; 230 LFS *fs; 231 ino_t ino; 232 233 printf("lfs_iset: setting ino %d daddr %lx time %lx\n", ip->i_number, daddr, atime); 234 235 fs = ip->i_lfs; 236 ino = ip->i_number; 237 LFS_IENTRY(ifp, fs, ino, bp); 238 239 ifp->if_daddr = daddr; 240 ifp->if_st_atime = atime; 241 lfs_bwrite(bp); 242 } 243 #endif /* LOGFS */ 244