Commit | Line | Data |
---|---|---|
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 | ||
27 | extern u_long nextgennumber; | |
ddd9f644 KB |
28 | |
29 | /* Allocate a new inode. */ | |
30 | /* ARGSUSED */ | |
31 | int | |
fc250aa9 MS |
32 | lfs_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 | 127 | int |
0b4d6502 | 128 | lfs_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 |
155 | ip->i_din.di_spare[0] = 0xdeadbeef; |
156 | ip->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 | 173 | int |
fc250aa9 MS |
174 | lfs_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 | } |