daddr_t => ufs_daddr_t
[unix-history] / usr / src / sys / ufs / lfs / lfs_alloc.c
CommitLineData
da7c5cc6 1/*
ad0f93d2
KB
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
202a4bd9 6 *
89e2bb79 7 * @(#)lfs_alloc.c 8.5 (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
fc250aa9
MS
32lfs_valloc(ap)
33 struct vop_valloc_args /* {
34 struct vnode *a_pvp;
35 int a_mode;
36 struct ucred *a_cred;
37 struct vnode **a_vpp;
38 } */ *ap;
e3fe2d69 39{
4bed3ffc 40 struct lfs *fs;
889a3fb1
KB
41 struct buf *bp;
42 struct ifile *ifp;
43 struct inode *ip;
44 struct vnode *vp;
89e2bb79 45 ufs_daddr_t blkno;
0b4d6502 46 ino_t new_ino;
889a3fb1 47 u_long i, max;
67e8af50 48 int error;
e3fe2d69 49
275ca4f0 50 /* Get the head of the freelist. */
e1b76915 51 fs = VTOI(ap->a_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);
205e11aa
MS
72 lfs_balloc(vp, fs->lfs_bsize, blkno, &bp);
73 ip->i_size += fs->lfs_bsize;
74 vnode_pager_setsize(vp, (u_long)ip->i_size);
75 vnode_pager_uncache(vp);
76
889a3fb1
KB
77 i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) *
78 fs->lfs_ifpb;
889a3fb1
KB
79 fs->lfs_free = i;
80 max = i + fs->lfs_ifpb;
cb84e0ab 81 for (ifp = (struct ifile *)bp->b_data; i < max; ++ifp) {
889a3fb1
KB
82 ifp->if_version = 1;
83 ifp->if_daddr = LFS_UNUSED_DADDR;
84 ifp->if_nextfree = ++i;
85 }
86 ifp--;
87 ifp->if_nextfree = LFS_UNUSED_INUM;
03dc7bb7
KB
88 if (error = VOP_BWRITE(bp))
89 return (error);
889a3fb1 90 }
07670f7d 91
275ca4f0 92 /* Create a vnode to associate with the inode. */
e1b76915 93 if (error = lfs_vcreate(ap->a_pvp->v_mount, new_ino, &vp))
7188ac27 94 return (error);
aeaa793c 95
0b4d6502 96
205e11aa 97 ip = VTOI(vp);
889a3fb1 98 /* Zero out the direct and indirect block addresses. */
aeaa793c
MS
99 bzero(&ip->i_din, sizeof(struct dinode));
100 ip->i_din.di_inumber = new_ino;
889a3fb1 101
275ca4f0 102 /* Set a new generation number for this inode. */
fb92d0ab
KM
103 if (++nextgennumber < (u_long)time.tv_sec)
104 nextgennumber = time.tv_sec;
105 ip->i_gen = nextgennumber;
e3fe2d69 106
275ca4f0 107 /* Insert into the inode hash table. */
ddd9f644 108 ufs_ihashins(ip);
743f1ef7 109
aeaa793c
MS
110 if (error = ufs_vinit(vp->v_mount, lfs_specop_p, LFS_FIFOOPS, &vp)) {
111 vput(vp);
112 *ap->a_vpp = NULL;
113 return (error);
114 }
115
116 *ap->a_vpp = vp;
117 vp->v_flag |= VDIROP;
118 VREF(ip->i_devvp);
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{
9342689a 133 extern int (**lfs_vnodeop_p)();
889a3fb1
KB
134 struct inode *ip;
135 struct ufsmount *ump;
0b4d6502
KB
136 int error, i;
137
275ca4f0 138 /* Create the vnode. */
9342689a 139 if (error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, vpp)) {
4c5ed28a 140 *vpp = NULL;
5e1f6927 141 return (error);
4c5ed28a 142 }
0b4d6502 143
275ca4f0 144 /* Get a pointer to the private mount structure. */
0b4d6502
KB
145 ump = VFSTOUFS(mp);
146
147 /* Initialize the inode. */
4c5ed28a
KM
148 MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK);
149 (*vpp)->v_data = ip;
a58cc97d 150 ip->i_vnode = *vpp;
1ef966ee 151 ip->i_devvp = ump->um_devvp;
cf5ef508 152 ip->i_flag = IN_MODIFIED;
a58cc97d 153 ip->i_dev = ump->um_dev;
aeaa793c 154 ip->i_number = ip->i_din.di_inumber = ino;
205e11aa
MS
155ip->i_din.di_spare[0] = 0xdeadbeef;
156ip->i_din.di_spare[1] = 0xdeadbeef;
a58cc97d 157 ip->i_lfs = ump->um_lfs;
0b4d6502
KB
158#ifdef QUOTA
159 for (i = 0; i < MAXQUOTAS; i++)
160 ip->i_dquot[i] = NODQUOT;
161#endif
1ef966ee
KB
162 ip->i_lockf = 0;
163 ip->i_diroff = 0;
164 ip->i_mode = 0;
165 ip->i_size = 0;
a5d64982 166 ip->i_blocks = 0;
03dc7bb7 167 ++ump->um_lfs->lfs_uinodes;
0b4d6502 168 return (0);
e3fe2d69 169}
d5075120 170
ddd9f644
KB
171/* Free an inode. */
172/* ARGUSED */
988dbbfa 173int
fc250aa9
MS
174lfs_vfree(ap)
175 struct vop_vfree_args /* {
176 struct vnode *a_pvp;
177 ino_t a_ino;
178 int a_mode;
179 } */ *ap;
275ca4f0 180{
01932c99 181 SEGUSE *sup;
889a3fb1
KB
182 struct buf *bp;
183 struct ifile *ifp;
184 struct inode *ip;
4bed3ffc 185 struct lfs *fs;
89e2bb79 186 ufs_daddr_t old_iaddr;
275ca4f0
KB
187 ino_t ino;
188
ddd9f644 189 /* Get the inode number and file system. */
fa870596 190 ip = VTOI(ap->a_pvp);
275ca4f0
KB
191 fs = ip->i_lfs;
192 ino = ip->i_number;
cf5ef508 193 if (ip->i_flag & IN_MODIFIED) {
03dc7bb7 194 --fs->lfs_uinodes;
cf5ef508
KB
195 ip->i_flag &=
196 ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
03dc7bb7 197 }
ddd9f644 198 /*
1344ae31
KB
199 * Set the ifile's inode entry to unused, increment its version number
200 * and link it into the free chain.
ddd9f644 201 */
275ca4f0 202 LFS_IENTRY(ifp, fs, ino, bp);
01932c99 203 old_iaddr = ifp->if_daddr;
ddd9f644
KB
204 ifp->if_daddr = LFS_UNUSED_DADDR;
205 ++ifp->if_version;
206 ifp->if_nextfree = fs->lfs_free;
207 fs->lfs_free = ino;
03dc7bb7 208 (void) VOP_BWRITE(bp);
ddd9f644 209
01932c99
CS
210 if (old_iaddr != LFS_UNUSED_DADDR) {
211 LFS_SEGENTRY(sup, fs, datosn(fs, old_iaddr), bp);
212#ifdef DIAGNOSTIC
213 if (sup->su_nbytes < sizeof(struct dinode))
214 panic("lfs_vfree: negative byte count (segment %d)\n",
215 datosn(fs, old_iaddr));
216#endif
217 sup->su_nbytes -= sizeof(struct dinode);
03dc7bb7 218 (void) VOP_BWRITE(bp);
01932c99
CS
219 }
220
ddd9f644
KB
221 /* Set superblock modified bit and decrement file count. */
222 fs->lfs_fmod = 1;
223 --fs->lfs_nfiles;
988dbbfa 224 return (0);
275ca4f0 225}