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.37 (Berkeley) 12/14/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_valloc(pvp, notused, cred, vpp) 30 VNODE *pvp, **vpp; 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 #ifdef VERBOSE 43 printf("lfs_valloc\n"); 44 #endif 45 /* Get the head of the freelist. */ 46 fs = VTOI(pvp)->i_lfs; 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 #ifdef ALLOCPRINT 60 printf("lfs_ialloc: allocate inode %d\n", new_ino); 61 #endif 62 63 /* 64 * Remove the inode from the free list and write the free list 65 * back. 66 */ 67 LFS_IENTRY(ifp, fs, new_ino, bp); 68 if (ifp->if_daddr != LFS_UNUSED_DADDR) 69 panic("lfs_ialloc: inuse inode on the free list"); 70 fs->lfs_free = ifp->if_nextfree; 71 ifp->if_st_atime = time.tv_sec; 72 LFS_IWRITE(fs, bp); 73 74 /* Create a vnode to associate with the inode. */ 75 if (error = lfs_vcreate(pvp->v_mount, new_ino, &vp)) 76 return (error); 77 *vpp = vp; 78 ip = VTOI(vp); 79 VREF(ip->i_devvp); 80 81 /* Set a new generation number for this inode. */ 82 if (++nextgennumber < (u_long)time.tv_sec) 83 nextgennumber = time.tv_sec; 84 ip->i_gen = nextgennumber; 85 86 /* Insert into the inode hash table. */ 87 ufs_ihashins(ip); 88 89 /* Set superblock modified bit and increment file count. */ 90 fs->lfs_fmod = 1; 91 ++fs->lfs_nfiles; 92 return (0); 93 } 94 95 /* Create a new vnode/inode pair and initialize what fields we can. */ 96 int 97 lfs_vcreate(mp, ino, vpp) 98 MOUNT *mp; 99 ino_t ino; 100 VNODE **vpp; 101 { 102 extern struct vnodeops lfs_vnodeops; 103 INODE *ip; 104 UFSMOUNT *ump; 105 int error, i; 106 107 #ifdef VERBOSE 108 printf("lfs_vcreate: ino %d\n", ino); 109 #endif 110 /* Create the vnode. */ 111 if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp)) 112 return (error); 113 114 /* Get a pointer to the private mount structure. */ 115 ump = VFSTOUFS(mp); 116 117 /* Initialize the inode. */ 118 ip = VTOI(*vpp); 119 ip->i_vnode = *vpp; 120 ip->i_flag = 0; 121 ip->i_mode = 0; 122 ip->i_diroff = 0; 123 ip->i_lockf = 0; 124 ip->i_dev = ump->um_dev; 125 ip->i_number = ip->i_din.di_inum = ino; 126 ip->i_lfs = ump->um_lfs; 127 ip->i_devvp = ump->um_devvp; 128 #ifdef QUOTA 129 for (i = 0; i < MAXQUOTAS; i++) 130 ip->i_dquot[i] = NODQUOT; 131 #endif 132 return (0); 133 } 134 135 /* Free an inode. */ 136 /* ARGUSED */ 137 void 138 lfs_vfree(vp, notused1, notused2) 139 VNODE *vp; 140 ino_t notused1; 141 int notused2; 142 { 143 BUF *bp; 144 IFILE *ifp; 145 INODE *ip; 146 struct lfs *fs; 147 ino_t ino; 148 149 ip = VTOI(vp); 150 #ifdef VERBOSE 151 printf("lfs_vfree: free %d\n", ip->i_number); 152 #endif 153 /* Get the inode number and file system. */ 154 fs = ip->i_lfs; 155 ino = ip->i_number; 156 157 /* 158 * Set the ifile's inode entry to unused, increment its version number 159 * and link it into the free chain. 160 */ 161 LFS_IENTRY(ifp, fs, ino, bp); 162 ifp->if_daddr = LFS_UNUSED_DADDR; 163 ++ifp->if_version; 164 ifp->if_nextfree = fs->lfs_free; 165 fs->lfs_free = ino; 166 LFS_IWRITE(fs, bp); 167 168 /* Set superblock modified bit and decrement file count. */ 169 fs->lfs_fmod = 1; 170 --fs->lfs_nfiles; 171 } 172