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