Commit | Line | Data |
---|---|---|
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 | ||
27 | extern u_long nextgennumber; | |
ddd9f644 KB |
28 | |
29 | /* Allocate a new inode. */ | |
30 | /* ARGSUSED */ | |
31 | int | |
9342689a JH |
32 | lfs_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); | |
74 | printf("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; | |
84 | printf("Extending ifile: first inum = %d\n", i); | |
85 | fs->lfs_free = i; | |
86 | max = i + fs->lfs_ifpb; | |
87 | printf("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; | |
98 | printf("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 | 133 | int |
0b4d6502 | 134 | lfs_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 | 178 | void |
9342689a JH |
179 | lfs_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 |