1 /* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_alloc.c 7.34 (Berkeley) 11/01/91 8 */ 9 10 #include <sys/param.h> 11 #include <sys/kernel.h> 12 #include <sys/buf.h> 13 #include <sys/vnode.h> 14 #include <sys/syslog.h> 15 #include <sys/mount.h> 16 17 #include <ufs/ufs/quota.h> 18 #include <ufs/ufs/inode.h> 19 #include <ufs/ufs/ufsmount.h> 20 21 #include <ufs/lfs/lfs.h> 22 #include <ufs/lfs/lfs_extern.h> 23 24 extern u_long nextgennumber; 25 26 /* Allocate a new inode. */ 27 /* ARGSUSED */ 28 int 29 lfs_ialloc(pip, notused, cred, ipp) 30 INODE *pip, **ipp; 31 int notused; 32 UCRED *cred; 33 { 34 struct lfs *fs; 35 BUF *bp; 36 IFILE *ifp; 37 INODE *ip; 38 VNODE *vp; 39 ino_t new_ino; 40 int error; 41 42 /* Get the head of the freelist. */ 43 fs = pip->i_lfs; 44 new_ino = fs->lfs_free; 45 if (new_ino == LFS_UNUSED_INUM) { 46 /* 47 * XXX 48 * Currently, no more inodes are allocated if the ifile fills 49 * up. The ifile should be extended instead. 50 */ 51 uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt); 52 log(LOG_ERR, "uid %d on %s: out of inodes\n", 53 cred->cr_uid, fs->lfs_fsmnt); 54 return (ENOSPC); 55 } 56 #ifdef ALLOCPRINT 57 printf("lfs_ialloc: allocate inode %d\n", new_ino); 58 #endif 59 60 /* Read the appropriate block from the ifile. */ 61 LFS_IENTRY(ifp, fs, new_ino, bp); 62 63 if (ifp->if_daddr != LFS_UNUSED_DADDR) 64 panic("lfs_ialloc: inuse inode on the free list"); 65 66 /* Remove from the free list, set the access time, write it back. */ 67 fs->lfs_free = ifp->if_nextfree; 68 ifp->if_st_atime = time.tv_sec; 69 lfs_bwrite(bp); 70 71 /* Create a vnode to associate with the inode. */ 72 error = lfs_vcreate(ITOV(pip)->v_mount, new_ino, &vp); 73 if (error) 74 return (error); 75 *ipp = ip = VTOI(vp); 76 77 /* Set a new generation number for this inode. */ 78 if (++nextgennumber < (u_long)time.tv_sec) 79 nextgennumber = time.tv_sec; 80 ip->i_gen = nextgennumber; 81 82 /* Insert into the inode hash table. */ 83 ufs_ihashins(ip); 84 85 /* Set superblock modified bit and increment file count. */ 86 fs->lfs_fmod = 1; 87 ++fs->lfs_nfiles; 88 return (0); 89 } 90 91 /* Create a new vnode/inode pair and initialize what fields we can. */ 92 int 93 lfs_vcreate(mp, ino, vpp) 94 MOUNT *mp; 95 ino_t ino; 96 VNODE **vpp; 97 { 98 INODE *ip; 99 UFSMOUNT *ump; 100 int error, i; 101 102 #ifdef ALLOCPRINT 103 printf("lfs_vcreate: ino %d\n", ino); 104 #endif 105 /* Create the vnode. */ 106 if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp)) 107 return (error); 108 109 /* Get a pointer to the private mount structure. */ 110 ump = VFSTOUFS(mp); 111 112 /* Initialize the inode. */ 113 ip = VTOI(*vpp); 114 ip->i_diroff = 0; 115 ip->i_devvp = ump->um_devvp; 116 ip->i_dev = ump->um_dev; 117 ip->i_flag = 0; 118 ip->i_lfs = ump->um_lfs; 119 ip->i_lockf = 0; 120 ip->i_mode = 0; 121 ip->i_number = ip->i_din.di_inum = ino; 122 ip->i_vnode = *vpp; 123 #ifdef QUOTA 124 for (i = 0; i < MAXQUOTAS; i++) 125 ip->i_dquot[i] = NODQUOT; 126 #endif 127 VREF(ip->i_devvp); /* XXX: Why? */ 128 return (0); 129 } 130 131 /* Free an inode. */ 132 /* ARGUSED */ 133 void 134 lfs_ifree(ip, notused1, notused2) 135 INODE *ip; 136 ino_t notused1; 137 int notused2; 138 { 139 BUF *bp; 140 IFILE *ifp; 141 struct lfs *fs; 142 ino_t ino; 143 144 #ifdef ALLOCPRINT 145 printf("lfs_ifree: free %d\n", ip->i_number); 146 #endif 147 /* Get the inode number and file system. */ 148 fs = ip->i_lfs; 149 ino = ip->i_number; 150 151 /* 152 * Read the appropriate block from the ifile. Set the inode entry to 153 * unused, increment its version number and link it into the free chain. 154 */ 155 LFS_IENTRY(ifp, fs, ino, bp); 156 ifp->if_daddr = LFS_UNUSED_DADDR; 157 ++ifp->if_version; 158 ifp->if_nextfree = fs->lfs_free; 159 fs->lfs_free = ino; 160 161 lfs_bwrite(bp); 162 163 /* Set superblock modified bit and decrement file count. */ 164 fs->lfs_fmod = 1; 165 --fs->lfs_nfiles; 166 } 167