lint
[unix-history] / usr / src / sys / ufs / lfs / lfs_alloc.c
CommitLineData
da7c5cc6 1/*
4bed3ffc 2 * Copyright (c) 1991 Regents of the University of California.
202a4bd9 3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
202a4bd9 6 *
80e9de4e 7 * @(#)lfs_alloc.c 7.42 (Berkeley) %G%
da7c5cc6 8 */
e3fe2d69 9
ddd9f644
KB
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>
4c5ed28a 16#include <sys/malloc.h>
c6f5111d 17
80e9de4e
KM
18#include <vm/vm.h>
19
4bed3ffc
KB
20#include <ufs/ufs/quota.h>
21#include <ufs/ufs/inode.h>
22#include <ufs/ufs/ufsmount.h>
ddd9f644 23
4bed3ffc
KB
24#include <ufs/lfs/lfs.h>
25#include <ufs/lfs/lfs_extern.h>
26
27extern u_long nextgennumber;
ddd9f644
KB
28
29/* Allocate a new inode. */
30/* ARGSUSED */
31int
a58cc97d 32lfs_valloc(pvp, notused, cred, vpp)
889a3fb1 33 struct vnode *pvp, **vpp;
ddd9f644 34 int notused;
889a3fb1 35 struct ucred *cred;
e3fe2d69 36{
4bed3ffc 37 struct lfs *fs;
889a3fb1
KB
38 struct buf *bp;
39 struct ifile *ifp;
40 struct inode *ip;
41 struct vnode *vp;
42 daddr_t blkno;
0b4d6502 43 ino_t new_ino;
889a3fb1 44 u_long i, max;
0b4d6502 45 int error;
e3fe2d69 46
a71716ec
KB
47#ifdef VERBOSE
48 printf("lfs_valloc\n");
49#endif
275ca4f0 50 /* Get the head of the freelist. */
a58cc97d 51 fs = VTOI(pvp)->i_lfs;
0b4d6502 52 new_ino = fs->lfs_free;
ddd9f644
KB
53#ifdef ALLOCPRINT
54 printf("lfs_ialloc: allocate inode %d\n", new_ino);
55#endif
0b4d6502 56
1344ae31 57 /*
889a3fb1
KB
58 * Remove the inode from the free list and write the new start
59 * of the free list into the superblock.
1344ae31 60 */
0b4d6502 61 LFS_IENTRY(ifp, fs, new_ino, bp);
0b4d6502 62 if (ifp->if_daddr != LFS_UNUSED_DADDR)
275ca4f0 63 panic("lfs_ialloc: inuse inode on the free list");
0b4d6502 64 fs->lfs_free = ifp->if_nextfree;
889a3fb1
KB
65 brelse(bp);
66
67 /* Extend IFILE so that the next lfs_valloc will succeed. */
68 if (fs->lfs_free == LFS_UNUSED_INUM) {
69 vp = fs->lfs_ivnode;
70 ip = VTOI(vp);
71 blkno = lblkno(fs, ip->i_size);
72printf("Extending ifile: blkno = %d\n", blkno);
73 bp = getblk(vp, blkno, fs->lfs_bsize);
74 if (!bp) {
75 uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt);
76 log(LOG_ERR, "uid %d on %s: out of inodes\n",
77 cred->cr_uid, fs->lfs_fsmnt);
78 return (ENOSPC);
79 }
80 i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) *
81 fs->lfs_ifpb;
82printf("Extending ifile: first inum = %d\n", i);
83 fs->lfs_free = i;
84 max = i + fs->lfs_ifpb;
85printf("Extending ifile: max inum = %d\n", max);
86 for (ifp = (struct ifile *)bp->b_un.b_words; i < max; ++ifp) {
87 ifp->if_version = 1;
88 ifp->if_daddr = LFS_UNUSED_DADDR;
89 ifp->if_nextfree = ++i;
90 }
91 ifp--;
92 ifp->if_nextfree = LFS_UNUSED_INUM;
93
94 ++ip->i_blocks; /* XXX This may not be right. */
95 ip->i_size += fs->lfs_bsize;
96printf("Extending ifile: blocks = %d size = %d\n", ip->i_blocks, ip->i_size);
80e9de4e 97 vnode_pager_setsize(vp, (u_long)ip->i_size);
889a3fb1
KB
98 vnode_pager_uncache(vp);
99 LFS_UBWRITE(bp);
100 }
07670f7d 101
275ca4f0 102 /* Create a vnode to associate with the inode. */
a58cc97d 103 if (error = lfs_vcreate(pvp->v_mount, new_ino, &vp))
7188ac27 104 return (error);
a58cc97d
KM
105 *vpp = vp;
106 ip = VTOI(vp);
107 VREF(ip->i_devvp);
0b4d6502 108
889a3fb1
KB
109 /* Zero out the direct and indirect block addresses. */
110 bzero(ip->i_db, (NDADDR + NIADDR) * sizeof(daddr_t));
111
275ca4f0 112 /* Set a new generation number for this inode. */
fb92d0ab
KM
113 if (++nextgennumber < (u_long)time.tv_sec)
114 nextgennumber = time.tv_sec;
115 ip->i_gen = nextgennumber;
e3fe2d69 116
275ca4f0 117 /* Insert into the inode hash table. */
ddd9f644 118 ufs_ihashins(ip);
743f1ef7 119
275ca4f0
KB
120 /* Set superblock modified bit and increment file count. */
121 fs->lfs_fmod = 1;
122 ++fs->lfs_nfiles;
0b4d6502 123 return (0);
e3fe2d69
KM
124}
125
275ca4f0 126/* Create a new vnode/inode pair and initialize what fields we can. */
0a0d4fba 127int
0b4d6502 128lfs_vcreate(mp, ino, vpp)
889a3fb1 129 struct mount *mp;
0b4d6502 130 ino_t ino;
889a3fb1 131 struct vnode **vpp;
e3fe2d69 132{
a58cc97d 133 extern struct vnodeops lfs_vnodeops;
889a3fb1
KB
134 struct inode *ip;
135 struct ufsmount *ump;
0b4d6502
KB
136 int error, i;
137
a71716ec 138#ifdef VERBOSE
ddd9f644
KB
139 printf("lfs_vcreate: ino %d\n", ino);
140#endif
275ca4f0 141 /* Create the vnode. */
4c5ed28a
KM
142 if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp)) {
143 *vpp = NULL;
5e1f6927 144 return (error);
4c5ed28a 145 }
0b4d6502 146
275ca4f0 147 /* Get a pointer to the private mount structure. */
0b4d6502
KB
148 ump = VFSTOUFS(mp);
149
150 /* Initialize the inode. */
4c5ed28a
KM
151 MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK);
152 (*vpp)->v_data = ip;
a58cc97d 153 ip->i_vnode = *vpp;
1ef966ee 154 ip->i_devvp = ump->um_devvp;
0b4d6502 155 ip->i_flag = 0;
a58cc97d 156 ip->i_dev = ump->um_dev;
d5075120 157 ip->i_number = ip->i_din.di_inum = ino;
a58cc97d 158 ip->i_lfs = ump->um_lfs;
0b4d6502
KB
159#ifdef QUOTA
160 for (i = 0; i < MAXQUOTAS; i++)
161 ip->i_dquot[i] = NODQUOT;
162#endif
1ef966ee
KB
163 ip->i_lockf = 0;
164 ip->i_diroff = 0;
165 ip->i_mode = 0;
166 ip->i_size = 0;
0b4d6502 167 return (0);
e3fe2d69 168}
d5075120 169
ddd9f644
KB
170/* Free an inode. */
171/* ARGUSED */
275ca4f0 172void
a58cc97d 173lfs_vfree(vp, notused1, notused2)
889a3fb1 174 struct vnode *vp;
ddd9f644
KB
175 ino_t notused1;
176 int notused2;
275ca4f0 177{
01932c99 178 SEGUSE *sup;
889a3fb1
KB
179 struct buf *bp;
180 struct ifile *ifp;
181 struct inode *ip;
4bed3ffc 182 struct lfs *fs;
01932c99 183 daddr_t old_iaddr;
275ca4f0
KB
184 ino_t ino;
185
a58cc97d 186 ip = VTOI(vp);
a71716ec
KB
187#ifdef VERBOSE
188 printf("lfs_vfree: free %d\n", ip->i_number);
ddd9f644
KB
189#endif
190 /* Get the inode number and file system. */
275ca4f0
KB
191 fs = ip->i_lfs;
192 ino = ip->i_number;
ddd9f644
KB
193
194 /*
1344ae31
KB
195 * Set the ifile's inode entry to unused, increment its version number
196 * and link it into the free chain.
ddd9f644 197 */
275ca4f0 198 LFS_IENTRY(ifp, fs, ino, bp);
01932c99 199 old_iaddr = ifp->if_daddr;
ddd9f644
KB
200 ifp->if_daddr = LFS_UNUSED_DADDR;
201 ++ifp->if_version;
202 ifp->if_nextfree = fs->lfs_free;
203 fs->lfs_free = ino;
889a3fb1 204 LFS_UBWRITE(bp);
ddd9f644 205
01932c99
CS
206 if (old_iaddr != LFS_UNUSED_DADDR) {
207 LFS_SEGENTRY(sup, fs, datosn(fs, old_iaddr), bp);
208#ifdef DIAGNOSTIC
209 if (sup->su_nbytes < sizeof(struct dinode))
210 panic("lfs_vfree: negative byte count (segment %d)\n",
211 datosn(fs, old_iaddr));
212#endif
213 sup->su_nbytes -= sizeof(struct dinode);
214 LFS_UBWRITE(bp);
215 }
216
ddd9f644
KB
217 /* Set superblock modified bit and decrement file count. */
218 fs->lfs_fmod = 1;
219 --fs->lfs_nfiles;
275ca4f0 220}